Cleanup: Replace UI button "string info" function

Instead of a single function with variadic arguments, a special enum
type containing which string to request, and a special struct to
contain the request and the result, just use separate functions for
each request, and return a std::string by value. Also change the enum
item string access to just give access to the enum item itself and add
const in a few places as necessary.

The callers of the API function get much clearer this way, and it's
much easier to see which information is used to create certain tooltip
strings.
This commit is contained in:
Hans Goudey
2024-01-18 23:12:09 -05:00
parent cb787a458b
commit 90c4e2e6ec
6 changed files with 324 additions and 497 deletions

View File

@@ -1412,47 +1412,30 @@ const bContextStore *UI_but_context_get(const uiBut *but);
void UI_but_unit_type_set(uiBut *but, int unit_type);
int UI_but_unit_type_get(const uiBut *but);
enum uiStringInfoType {
/**
* Ignore this item, use when accessing the data should be done conditionally.
*/
BUT_GET_NOP = 0,
BUT_GET_RNAPROP_IDENTIFIER,
BUT_GET_RNASTRUCT_IDENTIFIER,
BUT_GET_RNAENUM_IDENTIFIER,
BUT_GET_LABEL,
/**
* Query the result of #uiBut::tip_label_func().
* Meant to allow overriding the label to be displayed in the tool-tip.
*/
BUT_GET_TIP_LABEL,
BUT_GET_RNA_LABEL,
BUT_GET_RNAENUM_LABEL,
/** Context specified in `CTX_*_` macros are just unreachable! */
BUT_GET_RNA_LABEL_CONTEXT,
BUT_GET_TIP,
BUT_GET_RNA_TIP,
BUT_GET_RNAENUM_TIP,
/** Buttons assigned to an operator (common case). */
BUT_GET_OP_KEYMAP,
/** Use for properties that are bound to one of the context cycle, etc. keys. */
BUT_GET_PROP_KEYMAP,
};
struct uiStringInfo {
uiStringInfoType type;
char *strinfo;
};
std::optional<EnumPropertyItem> UI_but_rna_enum_item_get(bContext &C, uiBut &but);
std::string UI_but_string_get_rna_property_identifier(const uiBut &but);
std::string UI_but_string_get_rna_struct_identifier(const uiBut &but);
std::string UI_but_string_get_label(uiBut &but);
/**
* \note Expects pointers to #uiStringInfo structs as parameters.
* Will fill them with translated strings, when possible.
* Strings in #uiStringInfo must be MEM_freeN'ed by caller.
* Query the result of #uiBut::tip_label_func().
* Meant to allow overriding the label to be displayed in the tool-tip.
*/
void UI_but_string_info_get(bContext *C, uiBut *but, ...) ATTR_SENTINEL(0);
void UI_but_extra_icon_string_info_get(bContext *C, uiButExtraOpIcon *extra_icon, ...)
ATTR_SENTINEL(0);
std::string UI_but_string_get_tooltip_label(const uiBut &but);
std::string UI_but_string_get_rna_label(uiBut &but);
/** Context specified in `CTX_*_` macros are just unreachable! */
std::string UI_but_string_get_rna_label_context(const uiBut &but);
std::string UI_but_string_get_tooltip(bContext &C, uiBut &but);
std::string UI_but_string_get_rna_tooltip(bContext &C, uiBut &but);
/** Buttons assigned to an operator (common case). */
std::string UI_but_string_get_operator_keymap(bContext &C, uiBut &but);
/** Use for properties that are bound to one of the context cycle, etc. keys. */
std::string UI_but_string_get_property_keymap(bContext &C, uiBut &but);
std::string UI_but_extra_icon_string_get_label(const uiButExtraOpIcon &extra_icon);
std::string UI_but_extra_icon_string_get_tooltip(bContext &C, const uiButExtraOpIcon &extra_icon);
std::string UI_but_extra_icon_string_get_operator_keymap(const bContext &C,
const uiButExtraOpIcon &extra_icon);
/* Edit i18n stuff. */
/* Name of the main py op from i18n addon. */
@@ -1867,8 +1850,8 @@ PointerRNA *UI_but_extra_operator_icon_add(uiBut *but,
const char *opname,
wmOperatorCallContext opcontext,
int icon);
wmOperatorType *UI_but_extra_operator_icon_optype_get(uiButExtraOpIcon *extra_icon);
PointerRNA *UI_but_extra_operator_icon_opptr_get(uiButExtraOpIcon *extra_icon);
wmOperatorType *UI_but_extra_operator_icon_optype_get(const uiButExtraOpIcon *extra_icon);
PointerRNA *UI_but_extra_operator_icon_opptr_get(const uiButExtraOpIcon *extra_icon);
/**
* Get the scaled size for a preview button (typically #UI_BTyPE_PREVIEW_TILE) based on \a
@@ -2241,11 +2224,11 @@ wmOperatorType *UI_but_operatortype_get_from_enum_menu(uiBut *but, PropertyRNA *
/**
* This is a bit of a hack but best keep it in one place at least.
*/
MenuType *UI_but_menutype_get(uiBut *but);
MenuType *UI_but_menutype_get(const uiBut *but);
/**
* This is a bit of a hack but best keep it in one place at least.
*/
PanelType *UI_but_paneltype_get(uiBut *but);
PanelType *UI_but_paneltype_get(const uiBut *but);
void UI_menutype_draw(bContext *C, MenuType *mt, uiLayout *layout);
/**
* Used for popup panels only.

View File

@@ -1340,7 +1340,7 @@ static bool ui_but_event_operator_string(const bContext *C,
}
static bool ui_but_extra_icon_event_operator_string(const bContext *C,
uiButExtraOpIcon *extra_icon,
const uiButExtraOpIcon *extra_icon,
char *buf,
const size_t buf_maxncpy)
{
@@ -1715,12 +1715,12 @@ PointerRNA *UI_but_extra_operator_icon_add(uiBut *but,
return nullptr;
}
wmOperatorType *UI_but_extra_operator_icon_optype_get(uiButExtraOpIcon *extra_icon)
wmOperatorType *UI_but_extra_operator_icon_optype_get(const uiButExtraOpIcon *extra_icon)
{
return extra_icon ? extra_icon->optype_params->optype : nullptr;
}
PointerRNA *UI_but_extra_operator_icon_opptr_get(uiButExtraOpIcon *extra_icon)
PointerRNA *UI_but_extra_operator_icon_opptr_get(const uiButExtraOpIcon *extra_icon)
{
return extra_icon->optype_params->opptr;
}
@@ -6563,287 +6563,227 @@ void UI_but_func_hold_set(uiBut *but, uiButHandleHoldFunc func, void *argN)
but->hold_argN = argN;
}
void UI_but_string_info_get(bContext *C, uiBut *but, ...)
std::optional<EnumPropertyItem> UI_but_rna_enum_item_get(bContext &C, uiBut &but)
{
va_list args;
uiStringInfo *si;
PointerRNA *opptr = UI_but_operator_ptr_get(but);
const EnumPropertyItem *items = nullptr, *item = nullptr;
int totitems;
bool free_items = false;
va_start(args, but);
while ((si = (uiStringInfo *)va_arg(args, void *))) {
uiStringInfoType type = si->type;
std::optional<std::string> tmp;
if (type == BUT_GET_TIP_LABEL) {
if (but->tip_label_func) {
tmp = but->tip_label_func(but);
}
}
if (type == BUT_GET_LABEL) {
if (!but->str.empty()) {
size_t str_len = but->str.size();
if (but->flag & UI_BUT_HAS_SEP_CHAR) {
const size_t sep_index = but->str.find_first_of(UI_SEP_CHAR);
if (sep_index != std::string::npos) {
str_len = sep_index;
}
}
tmp = but->str.substr(0, str_len);
}
else {
type = BUT_GET_RNA_LABEL; /* Fail-safe solution... */
}
}
else if (type == BUT_GET_TIP) {
if (but->tip_func) {
tmp = but->tip_func(C, but->tip_arg, but->tip);
}
else if (but->tip && but->tip[0]) {
tmp = but->tip;
}
else {
type = BUT_GET_RNA_TIP; /* Fail-safe solution... */
}
}
if (type == BUT_GET_RNAPROP_IDENTIFIER) {
if (but->rnaprop) {
tmp = RNA_property_identifier(but->rnaprop);
}
}
else if (type == BUT_GET_RNASTRUCT_IDENTIFIER) {
if (but->rnaprop && but->rnapoin.data) {
tmp = RNA_struct_identifier(but->rnapoin.type);
}
else if (but->optype) {
tmp = but->optype->idname;
}
else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN)) {
MenuType *mt = UI_but_menutype_get(but);
if (mt) {
tmp = mt->idname;
}
}
else if (but->type == UI_BTYPE_POPOVER) {
PanelType *pt = UI_but_paneltype_get(but);
if (pt) {
tmp = pt->idname;
}
}
}
else if (ELEM(type, BUT_GET_RNA_LABEL, BUT_GET_RNA_TIP)) {
if (but->rnaprop) {
if (type == BUT_GET_RNA_LABEL) {
tmp = RNA_property_ui_name(but->rnaprop);
}
else {
const char *t = RNA_property_ui_description(but->rnaprop);
if (t && t[0]) {
tmp = t;
}
}
}
else if (but->optype) {
if (type == BUT_GET_RNA_LABEL) {
tmp = WM_operatortype_name(but->optype, opptr).c_str();
}
else {
const bContextStore *previous_ctx = CTX_store_get(C);
CTX_store_set(C, but->context);
tmp = WM_operatortype_description(C, but->optype, opptr).c_str();
CTX_store_set(C, previous_ctx);
}
}
else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)) {
{
MenuType *mt = UI_but_menutype_get(but);
if (mt) {
if (type == BUT_GET_RNA_LABEL) {
tmp = CTX_TIP_(mt->translation_context, mt->label);
}
else {
/* Not all menus are from Python. */
if (mt->rna_ext.srna) {
const char *t = RNA_struct_ui_description(mt->rna_ext.srna);
if (t && t[0]) {
tmp = t;
}
}
}
}
}
if (!tmp) {
wmOperatorType *ot = UI_but_operatortype_get_from_enum_menu(but, nullptr);
if (ot) {
if (type == BUT_GET_RNA_LABEL) {
tmp = WM_operatortype_name(ot, nullptr).c_str();
}
else {
tmp = WM_operatortype_description(C, ot, nullptr).c_str();
}
}
}
if (!tmp) {
PanelType *pt = UI_but_paneltype_get(but);
if (pt) {
if (type == BUT_GET_RNA_LABEL) {
tmp = CTX_TIP_(pt->translation_context, pt->label);
}
else {
/* Not all panels are from Python. */
if (pt->rna_ext.srna) {
/* Panels don't yet have descriptions, this may be added. */
}
}
}
}
}
}
else if (type == BUT_GET_RNA_LABEL_CONTEXT) {
const char *_tmp = BLT_I18NCONTEXT_DEFAULT;
if (but->rnaprop) {
_tmp = RNA_property_translation_context(but->rnaprop);
}
else if (but->optype) {
_tmp = RNA_struct_translation_context(but->optype->srna);
}
else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN)) {
MenuType *mt = UI_but_menutype_get(but);
if (mt) {
_tmp = RNA_struct_translation_context(mt->rna_ext.srna);
}
}
if (BLT_is_default_context(_tmp)) {
_tmp = BLT_I18NCONTEXT_DEFAULT_BPYRNA;
}
tmp = _tmp;
}
else if (ELEM(type, BUT_GET_RNAENUM_IDENTIFIER, BUT_GET_RNAENUM_LABEL, BUT_GET_RNAENUM_TIP)) {
PointerRNA *ptr = nullptr;
PropertyRNA *prop = nullptr;
int value = 0;
/* get the enum property... */
if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM) {
/* enum property */
ptr = &but->rnapoin;
prop = but->rnaprop;
value = ELEM(but->type, UI_BTYPE_ROW, UI_BTYPE_TAB) ? int(but->hardmax) :
int(ui_but_value_get(but));
}
else if (but->optype) {
wmOperatorType *ot = but->optype;
/* So the context is passed to `itemf` functions. */
WM_operator_properties_sanitize(opptr, false);
/* if the default property of the operator is enum and it is set,
* fetch the tooltip of the selected value so that "Snap" and "Mirror"
* operator menus in the Anim Editors will show tooltips for the different
* operations instead of the meaningless generic operator tooltip
*/
if (ot->prop && RNA_property_type(ot->prop) == PROP_ENUM) {
if (RNA_struct_contains_property(opptr, ot->prop)) {
ptr = opptr;
prop = ot->prop;
value = RNA_property_enum_get(opptr, ot->prop);
}
}
}
/* get strings from matching enum item */
if (ptr && prop) {
if (!item) {
int i;
RNA_property_enum_items_gettexted(C, ptr, prop, &items, &totitems, &free_items);
for (i = 0, item = items; i < totitems; i++, item++) {
if (item->identifier[0] && item->value == value) {
break;
}
}
}
if (item && item->identifier) {
if (type == BUT_GET_RNAENUM_IDENTIFIER) {
tmp = item->identifier;
}
else if (type == BUT_GET_RNAENUM_LABEL) {
tmp = item->name;
}
else if (item->description && item->description[0]) {
tmp = item->description;
}
}
}
}
/* NOTE: Menus will already have their shortcuts displayed.
* Pie menus are an exception as they already have a shortcut on display
* however this is only used within the context of the pie menu. */
else if (type == BUT_GET_OP_KEYMAP) {
char buf[128];
if (ui_but_event_operator_string(C, but, buf, sizeof(buf))) {
tmp = buf;
}
}
else if (type == BUT_GET_PROP_KEYMAP) {
char buf[128];
if (ui_but_event_property_operator_string(C, but, buf, sizeof(buf))) {
tmp = buf;
}
}
si->strinfo = tmp ? BLI_strdupn(tmp->c_str(), tmp->size()) : nullptr;
PointerRNA *ptr = nullptr;
PropertyRNA *prop = nullptr;
int value = 0;
if (but.rnaprop && RNA_property_type(but.rnaprop) == PROP_ENUM) {
ptr = &but.rnapoin;
prop = but.rnaprop;
value = ELEM(but.type, UI_BTYPE_ROW, UI_BTYPE_TAB) ? int(but.hardmax) :
int(ui_but_value_get(&but));
}
va_end(args);
else if (but.optype) {
wmOperatorType *ot = but.optype;
if (free_items && items) {
MEM_freeN((void *)items);
/* So the context is passed to `itemf` functions. */
PointerRNA *opptr = UI_but_operator_ptr_get(&but);
WM_operator_properties_sanitize(opptr, false);
/* If the default property of the operator is an enum and is set, fetch the tooltip of the
* selected value so that "Snap" and "Mirror" operator menus in the Animation Editors will
* show tooltips for the different operations instead of the meaningless generic tooltip. */
if (ot->prop && RNA_property_type(ot->prop) == PROP_ENUM) {
if (RNA_struct_contains_property(opptr, ot->prop)) {
ptr = opptr;
prop = ot->prop;
value = RNA_property_enum_get(opptr, ot->prop);
}
}
}
if (!ptr || !prop) {
return std::nullopt;
}
EnumPropertyItem item;
if (!RNA_property_enum_item_from_value_gettexted(&C, ptr, prop, value, &item)) {
return std::nullopt;
}
return item;
}
void UI_but_extra_icon_string_info_get(bContext *C, uiButExtraOpIcon *extra_icon, ...)
std::string UI_but_string_get_rna_property_identifier(const uiBut &but)
{
va_list args;
uiStringInfo *si;
if (!but.rnaprop) {
return {};
}
return RNA_property_identifier(but.rnaprop);
}
wmOperatorType *optype = UI_but_extra_operator_icon_optype_get(extra_icon);
PointerRNA *opptr = UI_but_extra_operator_icon_opptr_get(extra_icon);
std::string UI_but_string_get_rna_struct_identifier(const uiBut &but)
{
if (but.rnaprop && but.rnapoin.data) {
return RNA_struct_identifier(but.rnapoin.type);
}
if (but.optype) {
return but.optype->idname;
}
if (ELEM(but.type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN)) {
if (MenuType *mt = UI_but_menutype_get(&but)) {
return mt->idname;
}
}
if (but.type == UI_BTYPE_POPOVER) {
if (PanelType *pt = UI_but_paneltype_get(&but)) {
return pt->idname;
}
}
return {};
}
va_start(args, extra_icon);
while ((si = (uiStringInfo *)va_arg(args, void *))) {
std::string tmp;
switch (si->type) {
case BUT_GET_LABEL:
tmp = WM_operatortype_name(optype, opptr);
break;
case BUT_GET_TIP:
tmp = WM_operatortype_description(C, optype, opptr);
break;
case BUT_GET_OP_KEYMAP: {
char buf[128];
if (ui_but_extra_icon_event_operator_string(C, extra_icon, buf, sizeof(buf))) {
tmp = buf;
}
break;
std::string UI_but_string_get_label(uiBut &but)
{
if (!but.str.empty()) {
size_t str_len = but.str.size();
if (but.flag & UI_BUT_HAS_SEP_CHAR) {
const size_t sep_index = but.str.find_first_of(UI_SEP_CHAR);
if (sep_index != std::string::npos) {
str_len = sep_index;
}
default:
/* Other types not supported. The caller should expect that outcome, no need to message or
* assert here. */
break;
}
return but.str.substr(0, str_len);
}
return UI_but_string_get_rna_label(but);
}
std::string UI_but_string_get_tooltip_label(const uiBut &but)
{
if (!but.tip_label_func) {
return {};
}
return but.tip_label_func(&but);
}
std::string UI_but_string_get_rna_label(uiBut &but)
{
if (but.rnaprop) {
return RNA_property_ui_name(but.rnaprop);
}
if (but.optype) {
PointerRNA *opptr = UI_but_operator_ptr_get(&but);
return WM_operatortype_name(but.optype, opptr).c_str();
}
if (ELEM(but.type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)) {
if (MenuType *mt = UI_but_menutype_get(&but)) {
return CTX_TIP_(mt->translation_context, mt->label);
}
si->strinfo = BLI_strdupn(tmp.c_str(), tmp.size());
if (wmOperatorType *ot = UI_but_operatortype_get_from_enum_menu(&but, nullptr)) {
return WM_operatortype_name(ot, nullptr).c_str();
}
if (PanelType *pt = UI_but_paneltype_get(&but)) {
return CTX_TIP_(pt->translation_context, pt->label);
}
}
va_end(args);
return {};
}
std::string UI_but_string_get_rna_label_context(const uiBut &but)
{
if (but.rnaprop) {
return RNA_property_translation_context(but.rnaprop);
}
if (but.optype) {
return RNA_struct_translation_context(but.optype->srna);
}
if (ELEM(but.type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN)) {
if (MenuType *mt = UI_but_menutype_get(&but)) {
return RNA_struct_translation_context(mt->rna_ext.srna);
}
}
return BLT_I18NCONTEXT_DEFAULT_BPYRNA;
}
std::string UI_but_string_get_tooltip(bContext &C, uiBut &but)
{
if (but.tip_func) {
return but.tip_func(&C, but.tip_arg, but.tip);
}
if (but.tip && but.tip[0]) {
return but.tip;
}
return UI_but_string_get_rna_tooltip(C, but);
}
std::string UI_but_string_get_rna_tooltip(bContext &C, uiBut &but)
{
if (but.rnaprop) {
const char *t = RNA_property_ui_description(but.rnaprop);
if (t && t[0]) {
return t;
}
}
else if (but.optype) {
PointerRNA *opptr = UI_but_operator_ptr_get(&but);
const bContextStore *previous_ctx = CTX_store_get(&C);
CTX_store_set(&C, but.context);
std::string tmp = WM_operatortype_description(&C, but.optype, opptr).c_str();
CTX_store_set(&C, previous_ctx);
return tmp;
}
if (ELEM(but.type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)) {
if (MenuType *mt = UI_but_menutype_get(&but)) {
/* Not all menus are from Python. */
if (mt->rna_ext.srna) {
const char *t = RNA_struct_ui_description(mt->rna_ext.srna);
if (t && t[0]) {
return t;
}
}
}
if (wmOperatorType *ot = UI_but_operatortype_get_from_enum_menu(&but, nullptr)) {
return WM_operatortype_description(&C, ot, nullptr).c_str();
}
}
return {};
}
std::string UI_but_string_get_operator_keymap(bContext &C, uiBut &but)
{
char buf[128];
if (!ui_but_event_operator_string(&C, &but, buf, sizeof(buf))) {
return {};
}
return buf;
}
std::string UI_but_string_get_property_keymap(bContext &C, uiBut &but)
{
char buf[128];
if (!ui_but_event_property_operator_string(&C, &but, buf, sizeof(buf))) {
return {};
}
return buf;
}
std::string UI_but_extra_icon_string_get_label(const uiButExtraOpIcon &extra_icon)
{
wmOperatorType *optype = UI_but_extra_operator_icon_optype_get(&extra_icon);
PointerRNA *opptr = UI_but_extra_operator_icon_opptr_get(&extra_icon);
return WM_operatortype_name(optype, opptr);
}
std::string UI_but_extra_icon_string_get_tooltip(bContext &C, const uiButExtraOpIcon &extra_icon)
{
wmOperatorType *optype = UI_but_extra_operator_icon_optype_get(&extra_icon);
PointerRNA *opptr = UI_but_extra_operator_icon_opptr_get(&extra_icon);
return WM_operatortype_description(&C, optype, opptr);
}
std::string UI_but_extra_icon_string_get_operator_keymap(const bContext &C,
const uiButExtraOpIcon &extra_icon)
{
char buf[128];
if (!ui_but_extra_icon_event_operator_string(&C, &extra_icon, buf, sizeof(buf))) {
return {};
}
return buf;
}
/* Program Init/Exit */

View File

@@ -517,16 +517,8 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but, const wmEvent *ev
uiLayout *layout;
const bContextStore *previous_ctx = CTX_store_get(C);
{
uiStringInfo label = {BUT_GET_LABEL, nullptr};
/* highly unlikely getting the label ever fails */
UI_but_string_info_get(C, but, &label, nullptr);
pup = UI_popup_menu_begin(C, label.strinfo ? label.strinfo : "", ICON_NONE);
pup = UI_popup_menu_begin(C, UI_but_string_get_label(*but).c_str(), ICON_NONE);
layout = UI_popup_menu_layout(pup);
if (label.strinfo) {
MEM_freeN(label.strinfo);
}
set_layout_context_from_button(C, layout, but);
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);

View File

@@ -6114,7 +6114,7 @@ wmOperatorType *UI_but_operatortype_get_from_enum_menu(uiBut *but, PropertyRNA *
return nullptr;
}
MenuType *UI_but_menutype_get(uiBut *but)
MenuType *UI_but_menutype_get(const uiBut *but)
{
if (but->menu_create_func == ui_item_menutype_func) {
return (MenuType *)but->poin;
@@ -6122,7 +6122,7 @@ MenuType *UI_but_menutype_get(uiBut *but)
return nullptr;
}
PanelType *UI_but_paneltype_get(uiBut *but)
PanelType *UI_but_paneltype_get(const uiBut *but)
{
if (but->menu_create_func == ui_item_paneltype_func) {
return (PanelType *)but->poin;

View File

@@ -2010,17 +2010,6 @@ static int edittranslation_exec(bContext *C, wmOperator *op)
const char *root = U.i18ndir;
const char *uilng = BLT_lang_get();
uiStringInfo but_label = {BUT_GET_LABEL, nullptr};
uiStringInfo rna_label = {BUT_GET_RNA_LABEL, nullptr};
uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, nullptr};
uiStringInfo but_tip = {BUT_GET_TIP, nullptr};
uiStringInfo rna_tip = {BUT_GET_RNA_TIP, nullptr};
uiStringInfo enum_tip = {BUT_GET_RNAENUM_TIP, nullptr};
uiStringInfo rna_struct = {BUT_GET_RNASTRUCT_IDENTIFIER, nullptr};
uiStringInfo rna_prop = {BUT_GET_RNAPROP_IDENTIFIER, nullptr};
uiStringInfo rna_enum = {BUT_GET_RNAENUM_IDENTIFIER, nullptr};
uiStringInfo rna_ctxt = {BUT_GET_RNA_LABEL_CONTEXT, nullptr};
if (!BLI_is_dir(root)) {
BKE_report(op->reports,
RPT_ERROR,
@@ -2046,66 +2035,27 @@ static int edittranslation_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
UI_but_string_info_get(C,
but,
&but_label,
&rna_label,
&enum_label,
&but_tip,
&rna_tip,
&enum_tip,
&rna_struct,
&rna_prop,
&rna_enum,
&rna_ctxt,
nullptr);
WM_operator_properties_create_ptr(&ptr, ot);
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);
const int ret = WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, nullptr);
/* 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);
}
const EnumPropertyItem enum_item = UI_but_rna_enum_item_get(*C, *but).value_or(
EnumPropertyItem{});
RNA_string_set(&ptr, "enum_label", enum_item.name);
RNA_string_set(&ptr, "enum_tip", enum_item.description);
RNA_string_set(&ptr, "rna_enum", enum_item.identifier);
RNA_string_set(&ptr, "but_label", UI_but_string_get_label(*but).c_str());
RNA_string_set(&ptr, "rna_label", UI_but_string_get_rna_label(*but).c_str());
RNA_string_set(&ptr, "but_tip", UI_but_string_get_tooltip(*C, *but).c_str());
RNA_string_set(&ptr, "rna_tip", UI_but_string_get_rna_tooltip(*C, *but).c_str());
RNA_string_set(&ptr, "rna_struct", UI_but_string_get_rna_struct_identifier(*but).c_str());
RNA_string_set(&ptr, "rna_prop", UI_but_string_get_rna_property_identifier(*but).c_str());
RNA_string_set(&ptr, "rna_ctxt", UI_but_string_get_rna_label_context(*but).c_str());
const int ret = WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, nullptr);
return ret;
}

View File

@@ -586,15 +586,9 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
*
* Either way case it's useful to show the shortcut.
*/
char *shortcut = nullptr;
std::string shortcut = UI_but_string_get_operator_keymap(*C, *but);
{
uiStringInfo op_keymap = {BUT_GET_OP_KEYMAP, nullptr};
UI_but_string_info_get(C, but, &op_keymap, nullptr);
shortcut = op_keymap.strinfo;
}
if (shortcut == nullptr) {
if (shortcut.empty()) {
const ePaintMode paint_mode = BKE_paintmode_get_active_from_context(C);
const char *tool_attr = BKE_paint_get_tool_prop_id_from_paintmode(paint_mode);
if (tool_attr != nullptr) {
@@ -619,14 +613,14 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
shortcut_brush,
ARRAY_SIZE(shortcut_brush)))
{
shortcut = BLI_strdup(shortcut_brush);
shortcut = shortcut_brush;
}
WM_operator_properties_free(&op_props);
}
}
}
if (shortcut == nullptr) {
if (shortcut.empty()) {
/* Check for direct access to the tool. */
char shortcut_toolbar[128] = "";
if (WM_key_event_operator_string(C,
@@ -676,14 +670,13 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is
}
}
if (shortcut != nullptr) {
if (!shortcut.empty()) {
UI_tooltip_text_field_add(data,
BLI_sprintfN(TIP_("Shortcut: %s"), shortcut),
BLI_sprintfN(TIP_("Shortcut: %s"), shortcut.c_str()),
nullptr,
UI_TIP_STYLE_NORMAL,
UI_TIP_LC_VALUE,
true);
MEM_freeN(shortcut);
}
}
@@ -826,93 +819,91 @@ static uiTooltipData *ui_tooltip_data_from_button_or_extra_icon(bContext *C,
uiButExtraOpIcon *extra_icon,
const bool is_label)
{
uiStringInfo but_label = {BUT_GET_LABEL, nullptr};
uiStringInfo but_tip_label = {BUT_GET_TIP_LABEL, nullptr};
uiStringInfo but_tip = {BUT_GET_TIP, nullptr};
uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, nullptr};
uiStringInfo enum_tip = {BUT_GET_RNAENUM_TIP, nullptr};
uiStringInfo op_keymap = {BUT_GET_OP_KEYMAP, nullptr};
uiStringInfo prop_keymap = {BUT_GET_PROP_KEYMAP, nullptr};
uiStringInfo rna_struct = {BUT_GET_RNASTRUCT_IDENTIFIER, nullptr};
uiStringInfo rna_prop = {BUT_GET_RNAPROP_IDENTIFIER, nullptr};
char buf[512];
wmOperatorType *optype = extra_icon ? UI_but_extra_operator_icon_optype_get(extra_icon) :
but->optype;
PropertyRNA *rnaprop = extra_icon ? nullptr : but->rnaprop;
/* create tooltip data */
uiTooltipData *data = MEM_cnew<uiTooltipData>(__func__);
/* Menus already show shortcuts, don't show them in the tool-tips. */
if (ui_block_is_menu(but->block) && !ui_block_is_pie_menu(but->block)) {
op_keymap.type = BUT_GET_NOP;
prop_keymap.type = BUT_GET_NOP;
}
const bool is_menu = ui_block_is_menu(but->block) && !ui_block_is_pie_menu(but->block);
std::string but_label;
std::string but_tip;
std::string but_tip_label;
std::string op_keymap;
std::string prop_keymap;
std::string rna_struct;
std::string rna_prop;
std::string enum_label;
std::string enum_tip;
if (extra_icon) {
if (is_label) {
UI_but_extra_icon_string_info_get(
C, extra_icon, &but_tip_label, &but_label, &enum_label, nullptr);
but_label = UI_but_extra_icon_string_get_label(*extra_icon);
}
else {
UI_but_extra_icon_string_info_get(
C, extra_icon, &but_label, &but_tip_label, &but_tip, &op_keymap, nullptr);
but_label = UI_but_extra_icon_string_get_label(*extra_icon);
but_tip = UI_but_extra_icon_string_get_tooltip(*C, *extra_icon);
if (!is_menu) {
op_keymap = UI_but_extra_icon_string_get_operator_keymap(*C, *extra_icon);
}
}
}
else {
const std::optional<EnumPropertyItem> enum_item = UI_but_rna_enum_item_get(*C, *but);
if (is_label) {
UI_but_string_info_get(C, but, &but_tip_label, &but_label, &enum_label, nullptr);
but_tip_label = UI_but_string_get_tooltip_label(*but);
but_label = UI_but_string_get_label(*but);
enum_label = enum_item ? enum_item->name : "";
}
else {
UI_but_string_info_get(C,
but,
&but_label,
&but_tip_label,
&but_tip,
&enum_label,
&enum_tip,
&op_keymap,
&prop_keymap,
&rna_struct,
&rna_prop,
nullptr);
but_label = UI_but_string_get_label(*but);
but_tip_label = UI_but_string_get_tooltip_label(*but);
but_tip = UI_but_string_get_tooltip(*C, *but);
enum_label = enum_item ? enum_item->name : "";
enum_tip = enum_item ? enum_item->description : "";
if (!is_menu) {
op_keymap = UI_but_string_get_operator_keymap(*C, *but);
prop_keymap = UI_but_string_get_property_keymap(*C, *but);
}
rna_struct = UI_but_string_get_rna_struct_identifier(*but);
rna_prop = UI_but_string_get_rna_property_identifier(*but);
}
}
/* Label: If there is a custom tooltip label, use that to override the label to display.
* Otherwise fallback to the regular label. */
if (but_tip_label.strinfo) {
if (!but_tip_label.empty()) {
UI_tooltip_text_field_add(
data, BLI_strdup(but_tip_label.strinfo), nullptr, UI_TIP_STYLE_HEADER, UI_TIP_LC_NORMAL);
data, BLI_strdup(but_tip_label.c_str()), nullptr, UI_TIP_STYLE_HEADER, UI_TIP_LC_NORMAL);
}
/* Regular (non-custom) label. Only show when the button doesn't already show the label. Check
* prefix instead of comparing because the button may include the shortcut. Buttons with dynamic
* tool-tips also don't get their default label here since they can already provide more accurate
* and specific tool-tip content. */
else if (but_label.strinfo && !STRPREFIX(but->drawstr, but_label.strinfo) && !but->tip_func) {
else if (!but_label.empty() && !STRPREFIX(but->drawstr, but_label.c_str()) && !but->tip_func) {
UI_tooltip_text_field_add(
data, BLI_strdup(but_label.strinfo), nullptr, UI_TIP_STYLE_HEADER, UI_TIP_LC_NORMAL);
data, BLI_strdup(but_label.c_str()), nullptr, UI_TIP_STYLE_HEADER, UI_TIP_LC_NORMAL);
}
/* Tip */
if (but_tip.strinfo) {
{
if (enum_label.strinfo) {
UI_tooltip_text_field_add(data,
BLI_sprintfN("%s: ", but_tip.strinfo),
BLI_strdup(enum_label.strinfo),
UI_TIP_STYLE_HEADER,
UI_TIP_LC_NORMAL);
}
else {
UI_tooltip_text_field_add(data,
BLI_sprintfN("%s.", but_tip.strinfo),
nullptr,
UI_TIP_STYLE_HEADER,
UI_TIP_LC_NORMAL);
}
if (!but_tip.empty()) {
if (!enum_label.empty()) {
UI_tooltip_text_field_add(data,
BLI_sprintfN("%s: ", but_tip.c_str()),
BLI_strdup(enum_label.c_str()),
UI_TIP_STYLE_HEADER,
UI_TIP_LC_NORMAL);
}
else {
UI_tooltip_text_field_add(data,
BLI_sprintfN("%s.", but_tip.c_str()),
nullptr,
UI_TIP_STYLE_HEADER,
UI_TIP_LC_NORMAL);
}
/* special case enum rna buttons */
@@ -925,21 +916,21 @@ static uiTooltipData *ui_tooltip_data_from_button_or_extra_icon(bContext *C,
}
}
/* When there is only an enum label (no button label or tip), draw that as header. */
else if (enum_label.strinfo && !(but_label.strinfo && but_label.strinfo[0])) {
else if (!enum_label.empty() && but_label.empty()) {
UI_tooltip_text_field_add(
data, BLI_strdup(enum_label.strinfo), nullptr, UI_TIP_STYLE_HEADER, UI_TIP_LC_NORMAL);
data, BLI_strdup(enum_label.c_str()), nullptr, UI_TIP_STYLE_HEADER, UI_TIP_LC_NORMAL);
}
/* Enum field label & tip. */
if (enum_tip.strinfo) {
if (!enum_tip.empty()) {
UI_tooltip_text_field_add(
data, BLI_strdup(enum_tip.strinfo), nullptr, UI_TIP_STYLE_NORMAL, UI_TIP_LC_VALUE);
data, BLI_strdup(enum_tip.c_str()), nullptr, UI_TIP_STYLE_NORMAL, UI_TIP_LC_VALUE);
}
/* Operator shortcut. */
if (op_keymap.strinfo) {
if (!op_keymap.empty()) {
UI_tooltip_text_field_add(data,
BLI_sprintfN(TIP_("Shortcut: %s"), op_keymap.strinfo),
BLI_sprintfN(TIP_("Shortcut: %s"), op_keymap.c_str()),
nullptr,
UI_TIP_STYLE_NORMAL,
UI_TIP_LC_VALUE,
@@ -947,9 +938,9 @@ static uiTooltipData *ui_tooltip_data_from_button_or_extra_icon(bContext *C,
}
/* Property context-toggle shortcut. */
if (prop_keymap.strinfo) {
if (!prop_keymap.empty()) {
UI_tooltip_text_field_add(data,
BLI_sprintfN(TIP_("Shortcut: %s"), prop_keymap.strinfo),
BLI_sprintfN(TIP_("Shortcut: %s"), prop_keymap.c_str()),
nullptr,
UI_TIP_STYLE_NORMAL,
UI_TIP_LC_VALUE,
@@ -1065,13 +1056,13 @@ static uiTooltipData *ui_tooltip_data_from_button_or_extra_icon(bContext *C,
}
}
if ((U.flag & USER_TOOLTIPS_PYTHON) && !optype && rna_struct.strinfo) {
if ((U.flag & USER_TOOLTIPS_PYTHON) && !optype && !rna_struct.empty()) {
{
UI_tooltip_text_field_add(
data,
(rna_prop.strinfo) ?
BLI_sprintfN(TIP_("Python: %s.%s"), rna_struct.strinfo, rna_prop.strinfo) :
BLI_sprintfN(TIP_("Python: %s"), rna_struct.strinfo),
rna_prop.empty() ?
BLI_sprintfN(TIP_("Python: %s"), rna_struct.c_str()) :
BLI_sprintfN(TIP_("Python: %s.%s"), rna_struct.c_str(), rna_prop.c_str()),
nullptr,
UI_TIP_STYLE_MONO,
UI_TIP_LC_PYTHON,
@@ -1089,35 +1080,6 @@ static uiTooltipData *ui_tooltip_data_from_button_or_extra_icon(bContext *C,
}
}
/* Free strinfo's... */
if (but_label.strinfo) {
MEM_freeN(but_label.strinfo);
}
if (but_tip_label.strinfo) {
MEM_freeN(but_tip_label.strinfo);
}
if (but_tip.strinfo) {
MEM_freeN(but_tip.strinfo);
}
if (enum_label.strinfo) {
MEM_freeN(enum_label.strinfo);
}
if (enum_tip.strinfo) {
MEM_freeN(enum_tip.strinfo);
}
if (op_keymap.strinfo) {
MEM_freeN(op_keymap.strinfo);
}
if (prop_keymap.strinfo) {
MEM_freeN(prop_keymap.strinfo);
}
if (rna_struct.strinfo) {
MEM_freeN(rna_struct.strinfo);
}
if (rna_prop.strinfo) {
MEM_freeN(rna_prop.strinfo);
}
if (data->fields_len == 0) {
MEM_freeN(data);
return nullptr;