Merge pull request #89367 from KoBeWi/locale_shift

Allow rearranging translation list via drag and drop
This commit is contained in:
Thaddeus Crews
2025-10-09 11:46:55 -05:00
2 changed files with 107 additions and 0 deletions

View File

@@ -65,6 +65,12 @@ void LocalizationEditor::_notification(int p_what) {
_update_pot_file_extensions();
pot_generate_dialog->add_filter("*.pot");
} break;
case NOTIFICATION_DRAG_END: {
for (Tree *tree : trees) {
tree->set_drop_mode_flags(Tree::DROP_MODE_DISABLED);
}
} break;
}
}
@@ -503,6 +509,89 @@ void LocalizationEditor::_filesystem_file_removed(const String &p_file) {
}
}
Variant LocalizationEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
Tree *tree = Object::cast_to<Tree>(p_from);
ERR_FAIL_COND_V(trees.find(tree) == -1, Variant());
if (tree->get_button_id_at_position(p_point) != -1) {
return Variant();
}
TreeItem *selected = tree->get_next_selected(nullptr);
if (!selected) {
return Variant();
}
tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN);
Label *preview = memnew(Label);
preview->set_text(selected->get_text(0));
set_drag_preview(preview);
Dictionary drag_data;
drag_data["type"] = tree_data_types[tree];
drag_data["item"] = selected;
return drag_data;
}
bool LocalizationEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
Tree *tree = Object::cast_to<Tree>(p_from);
ERR_FAIL_COND_V(trees.find(tree) == -1, false);
Dictionary drop_data = p_data;
return drop_data.get("type", "") == tree_data_types[tree];
}
void LocalizationEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) {
Tree *tree = Object::cast_to<Tree>(p_from);
ERR_FAIL_COND(trees.find(tree) == -1);
if (!can_drop_data_fw(p_point, p_data, p_from)) {
return;
}
TreeItem *item = tree->get_item_at_position(p_point);
if (!item) {
return;
}
int section = MAX(tree->get_drop_section_at_position(p_point), 0);
Dictionary drop_data = p_data;
TreeItem *from = Object::cast_to<TreeItem>(drop_data["item"]);
if (item == from) {
return;
}
const StringName &setting = tree_settings[tree];
PackedStringArray setting_value = GLOBAL_GET(setting);
const PackedStringArray original_setting_value = setting_value;
const int index_from = from->get_metadata(0);
const String path = setting_value[index_from];
int target_index = item->get_metadata(0);
target_index = MAX(target_index + section, 0);
if (target_index > index_from) {
target_index -= 1; // Account for item being removed.
}
if (target_index == index_from) {
return;
}
setting_value.remove_at(index_from);
setting_value.insert(target_index, path);
EditorUndoRedoManager *ur_man = EditorUndoRedoManager::get_singleton();
ur_man->create_action(TTR("Rearrange Localization Items"));
ur_man->add_do_method(ProjectSettings::get_singleton(), "set", setting, setting_value);
ur_man->add_do_method(ProjectSettings::get_singleton(), "save");
ur_man->add_do_method(this, "update_translations");
ur_man->add_undo_method(ProjectSettings::get_singleton(), "set", setting, original_setting_value);
ur_man->add_undo_method(ProjectSettings::get_singleton(), "save");
ur_man->add_undo_method(this, "update_translations");
ur_man->commit_action();
}
void LocalizationEditor::update_translations() {
if (updating_translations) {
return;
@@ -652,6 +741,9 @@ LocalizationEditor::LocalizationEditor() {
translation_list = memnew(Tree);
translation_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
tmc->add_child(translation_list);
trees.push_back(translation_list);
tree_data_types[translation_list] = "localization_editor_translation_item";
tree_settings[translation_list] = "internationalization/locale/translations";
locale_select = memnew(EditorLocaleDialog);
locale_select->connect("locale_selected", callable_mp(this, &LocalizationEditor::_translation_res_option_selected));
@@ -755,6 +847,9 @@ LocalizationEditor::LocalizationEditor() {
translation_pot_list = memnew(Tree);
translation_pot_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
tvb->add_child(translation_pot_list);
trees.push_back(translation_pot_list);
tree_data_types[translation_pot_list] = "localization_editor_pot_item";
tree_settings[translation_pot_list] = "internationalization/locale/translations_pot_files";
translation_pot_add_builtin = memnew(CheckBox(TTRC("Add Built-in Strings to POT")));
translation_pot_add_builtin->set_tooltip_text(TTRC("Add strings from built-in components such as certain Control nodes."));
@@ -772,4 +867,8 @@ LocalizationEditor::LocalizationEditor() {
pot_file_open_dialog->connect("files_selected", callable_mp(this, &LocalizationEditor::_pot_add));
add_child(pot_file_open_dialog);
}
for (Tree *tree : trees) {
SET_DRAG_FORWARDING_GCD(tree, LocalizationEditor);
}
}

View File

@@ -60,6 +60,10 @@ class LocalizationEditor : public VBoxContainer {
bool updating_translations = false;
String localization_changed;
LocalVector<Tree *> trees;
HashMap<Tree *, String> tree_data_types;
HashMap<Tree *, StringName> tree_settings;
void _translation_file_open();
void _translation_add(const PackedStringArray &p_paths);
void _translation_delete(Object *p_item, int p_column, int p_button, MouseButton p_mouse_button);
@@ -86,6 +90,10 @@ class LocalizationEditor : public VBoxContainer {
void _filesystem_files_moved(const String &p_old_file, const String &p_new_file);
void _filesystem_file_removed(const String &p_file);
Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const;
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
protected:
void _notification(int p_what);
static void _bind_methods();