Repository: godotengine/godot
File: editor/settings/project_settings_editor.cpp (C++)

Code before:
	undo_redo->add_undo_method(this, "queue_save");
	undo_redo->commit_action();
}

void ProjectSettingsEditor::_update_action_map_editor() {
	Vector<ActionMapEditor::ActionInfo> actions;

	List<PropertyInfo> props;
	ProjectSettings::get_singleton()->get_property_list(&props);

	const Ref<Texture2D> builtin_icon = get_editor_theme_icon(SNAME("PinPressed"));
	for (const PropertyInfo &E : props) {
		const String property_name = E.name;

		if (!property_name.begins_with("input/")) {
			continue;
		}

		// Strip the "input/" from the left.
		String display_name = property_name.substr(String("input/").size() - 1);
		Dictionary action = GLOBAL_GET(property_name);

		if (!action.has("events")) {
			continue;
		}

		ActionMapEditor::ActionInfo action_info;
		action_info.action = action;
		action_info.editable = true;
		action_info.name = display_name;

		const bool is_builtin_input = ProjectSettings::get_singleton()->get_input_presets().find(property_name) != nullptr;
		if (is_builtin_input) {
			action_info.editable = false;
			action_info.icon = builtin_icon;
			action_info.has_initial = true;
			action_info.action_initial = ProjectSettings::get_singleton()->property_get_revert(property_name);
		}

		actions.push_back(action_info);
	}

	action_map_editor->update_action_list(actions);
}

void ProjectSettingsEditor::_update_theme() {
	add_button->set_button_icon(get_editor_theme_icon(SNAME("Add")));
	del_button->set_button_icon(get_editor_theme_icon(SNAME("Remove")));
	search_box->set_right_icon(get_editor_theme_icon(SNAME("Search")));
	restart_close_button->set_button_icon(get_editor_theme_icon(SNAME("Close")));
	restart_container->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree")));

Review comment (suggestion):
At least for the editor, should this report an error so users can fix their settings?

```suggestion
  
  		ERR_CONTINUE_EDMSG(!action.has("events"), vformat("Invalid input action in project settings: %s.", property_name));
```

Code after:
	undo_redo->add_undo_method(this, "queue_save");
	undo_redo->commit_action();
}

void ProjectSettingsEditor::_update_action_map_editor() {
	Vector<ActionMapEditor::ActionInfo> actions;

	List<PropertyInfo> props;
	ProjectSettings::get_singleton()->get_property_list(&props);

	const Ref<Texture2D> builtin_icon = get_editor_theme_icon(SNAME("PinPressed"));
	for (const PropertyInfo &E : props) {
		const String property_name = E.name;

		if (!property_name.begins_with("input/")) {
			continue;
		}

		// Strip the "input/" from the left.
		String display_name = property_name.substr(String("input/").size() - 1);
		Dictionary action = GLOBAL_GET(property_name);

		if (!action.has("events")) {
			WARN_PRINT_ONCE_ED(vformat("Attempted to load invalid input action from setting at \"%s\". The `input/` prefix should only be used for input actions, and cannot be changed in the settings editor. Consider changing the category.", property_name));
			continue;
		}

		ActionMapEditor::ActionInfo action_info;
		action_info.action = action;
		action_info.editable = true;
		action_info.name = display_name;

		const bool is_builtin_input = ProjectSettings::get_singleton()->get_input_presets().find(property_name) != nullptr;
		if (is_builtin_input) {
			action_info.editable = false;
			action_info.icon = builtin_icon;
			action_info.has_initial = true;
			action_info.action_initial = ProjectSettings::get_singleton()->property_get_revert(property_name);
		}

		actions.push_back(action_info);
	}

	action_map_editor->update_action_list(actions);
}

void ProjectSettingsEditor::_update_theme() {
	add_button->set_button_icon(get_editor_theme_icon(SNAME("Add")));
	del_button->set_button_icon(get_editor_theme_icon(SNAME("Remove")));
	search_box->set_right_icon(get_editor_theme_icon(SNAME("Search")));
	restart_close_button->set_button_icon(get_editor_theme_icon(SNAME("Close")));