Repository: godotengine/godot
File: editor/inspector/editor_inspector.cpp (C++)

Code before:
		} break;

		case MENU_OPEN_DOCS: {
			ScriptEditor::get_singleton()->goto_help("class:" + doc_class_name);
			EditorNode::get_singleton()->get_editor_main_screen()->select(EditorMainScreen::EDITOR_SCRIPT);
		} break;

		case MENU_UNFAVORITE_ALL: {
			emit_signal(SNAME("unfavorite_all"));
		} break;
	}
}

void EditorInspectorCategory::_popup_context_menu(const Point2i &p_position) {
	if (!is_favorite && doc_class_name.is_empty()) {
		return;
	}

	if (menu == nullptr) {
		menu = memnew(PopupMenu);

		if (is_favorite) {
			menu->add_item(TTRC("Unfavorite All"), MENU_UNFAVORITE_ALL);
		} else {
			menu->add_icon_shortcut(get_editor_theme_icon(SNAME("ActionCopy")), ED_GET_SHORTCUT("property_editor/copy_category_values"), MENU_COPY_VALUE);
			menu->add_icon_shortcut(get_editor_theme_icon(SNAME("ActionPaste")), ED_GET_SHORTCUT("property_editor/paste_category_values"), MENU_PASTE_VALUE);
			menu->add_item(TTRC("Open Documentation"), MENU_OPEN_DOCS);
			menu->set_item_disabled(-1, !EditorHelp::get_doc_data()->class_list.has(doc_class_name));
		}

		menu->connect(SceneStringName(id_pressed), callable_mp(this, &EditorInspectorCategory::_handle_menu_option));
		add_child(menu);
	}

	if (menu_icon_dirty) {
		if (is_favorite) {
			menu->set_item_icon(menu->get_item_index(MENU_UNFAVORITE_ALL), theme_cache.icon_unfavorite);
		} else {
			menu->set_item_icon(menu->get_item_index(MENU_OPEN_DOCS), theme_cache.icon_help);
		}
		menu_icon_dirty = false;
	}

	menu->set_position(p_position);
	menu->reset_size();
	menu->popup();
}

void EditorInspectorCategory::_update_icon() {
	if (is_favorite) {
		icon = theme_cache.icon_favorites;

Review comment (performance):
```suggestion
			menu->add_icon_shortcut(theme_cache.icon_copy, ED_GET_SHORTCUT("property_editor/copy_category_values"), MENU_COPY_VALUE);
			menu->add_icon_shortcut(theme_cache.icon_paste, ED_GET_SHORTCUT("property_editor/paste_category_values"), MENU_PASTE_VALUE);
```

Code after:
	if (scr.is_valid()) {
		StringName script_name = EditorNode::get_editor_data().script_class_get_name(scr->get_path());
		if (script_name != StringName()) {
			label = script_name;
		}
	}
	if (label.is_empty()) {
		label = info.name;
	}
	_update_icon();
}

void EditorInspectorCategory::set_doc_class_name(const String &p_name) {
	doc_class_name = p_name;
}

Size2 EditorInspectorCategory::get_minimum_size() const {
	Size2 ms;
	if (theme_cache.bold_font.is_valid()) {
		ms.height = theme_cache.bold_font->get_height(theme_cache.bold_font_size);
	}
	if (icon.is_valid()) {
		ms.height = MAX(theme_cache.class_icon_size, ms.height);
	}
	ms.height += theme_cache.vertical_separation;

	if (theme_cache.background.is_valid()) {
		ms.height += theme_cache.background->get_content_margin(SIDE_TOP) + theme_cache.background->get_content_margin(SIDE_BOTTOM);
	}

	return ms;
}

void EditorInspectorCategory::_collect_properties(const Object *p_object, LocalVector<String> &r_properties) const {
	List<PropertyInfo> property_list;
	p_object->get_property_list(&property_list, true);

	String current_category;
	for (const PropertyInfo &prop_info : property_list) {
		if (prop_info.usage & PROPERTY_USAGE_GROUP) {
			continue;
		}
		if (prop_info.usage & PROPERTY_USAGE_CATEGORY) {
			current_category = prop_info.name;
			continue;
		}
		if (!(prop_info.usage & PROPERTY_USAGE_EDITOR)) {
			continue;
		}
		if (!current_category.ends_with(info.name)) {
			continue;