editor_locale_dialog.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. /**************************************************************************/
  2. /* editor_locale_dialog.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #include "editor_locale_dialog.h"
  31. #include "core/project_settings.h"
  32. #include "editor/editor_node.h"
  33. #include "editor/editor_scale.h"
  34. #include "scene/gui/check_button.h"
  35. #include "scene/gui/line_edit.h"
  36. #include "scene/gui/option_button.h"
  37. #include "scene/gui/tree.h"
  38. static _FORCE_INLINE_ bool is_ascii_upper_case(char32_t c) {
  39. return (c >= 'A' && c <= 'Z');
  40. }
  41. static _FORCE_INLINE_ bool is_ascii_lower_case(char32_t c) {
  42. return (c >= 'a' && c <= 'z');
  43. }
  44. void EditorLocaleDialog::_bind_methods() {
  45. ClassDB::bind_method(D_METHOD("_filter_mode_changed"), &EditorLocaleDialog::_filter_mode_changed);
  46. ClassDB::bind_method(D_METHOD("_edit_filters"), &EditorLocaleDialog::_edit_filters);
  47. ClassDB::bind_method(D_METHOD("_toggle_advanced"), &EditorLocaleDialog::_toggle_advanced);
  48. ClassDB::bind_method(D_METHOD("_item_selected"), &EditorLocaleDialog::_item_selected);
  49. ClassDB::bind_method(D_METHOD("_filter_lang_option_changed"), &EditorLocaleDialog::_filter_lang_option_changed);
  50. ClassDB::bind_method(D_METHOD("_filter_script_option_changed"), &EditorLocaleDialog::_filter_script_option_changed);
  51. ClassDB::bind_method(D_METHOD("_filter_cnt_option_changed"), &EditorLocaleDialog::_filter_cnt_option_changed);
  52. ADD_SIGNAL(MethodInfo("locale_selected", PropertyInfo(Variant::STRING, "locale")));
  53. }
  54. void EditorLocaleDialog::ok_pressed() {
  55. if (edit_filters->is_pressed()) {
  56. return; // Do not update, if in filter edit mode.
  57. }
  58. String locale;
  59. if (lang_code->get_text().empty()) {
  60. return; // Language code is required.
  61. }
  62. locale = lang_code->get_text();
  63. if (!script_code->get_text().empty()) {
  64. locale += "_" + script_code->get_text();
  65. }
  66. if (!country_code->get_text().empty()) {
  67. locale += "_" + country_code->get_text();
  68. }
  69. if (!variant_code->get_text().empty()) {
  70. locale += "_" + variant_code->get_text();
  71. }
  72. emit_signal("locale_selected", TranslationServer::get_singleton()->standardize_locale(locale));
  73. hide();
  74. }
  75. void EditorLocaleDialog::_item_selected() {
  76. if (updating_lists) {
  77. return;
  78. }
  79. if (edit_filters->is_pressed()) {
  80. return; // Do not update, if in filter edit mode.
  81. }
  82. TreeItem *l = lang_list->get_selected();
  83. if (l) {
  84. lang_code->set_text(l->get_metadata(0).operator String());
  85. }
  86. TreeItem *s = script_list->get_selected();
  87. if (s) {
  88. script_code->set_text(s->get_metadata(0).operator String());
  89. }
  90. TreeItem *c = cnt_list->get_selected();
  91. if (c) {
  92. country_code->set_text(c->get_metadata(0).operator String());
  93. }
  94. }
  95. void EditorLocaleDialog::_toggle_advanced(bool p_checked) {
  96. if (!p_checked) {
  97. script_code->set_text("");
  98. variant_code->set_text("");
  99. }
  100. _update_tree();
  101. }
  102. void EditorLocaleDialog::_post_popup() {
  103. ConfirmationDialog::_post_popup();
  104. if (!locale_set) {
  105. lang_code->set_text("");
  106. script_code->set_text("");
  107. country_code->set_text("");
  108. variant_code->set_text("");
  109. }
  110. edit_filters->set_pressed(false);
  111. _update_tree();
  112. }
  113. void EditorLocaleDialog::_filter_lang_option_changed() {
  114. TreeItem *t = lang_list->get_edited();
  115. String lang = t->get_metadata(0);
  116. bool checked = t->is_checked(0);
  117. Variant prev;
  118. Array f_lang_all;
  119. if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/language_filter")) {
  120. f_lang_all = ProjectSettings::get_singleton()->get("internationalization/locale/language_filter");
  121. prev = f_lang_all;
  122. }
  123. int l_idx = f_lang_all.find(lang);
  124. if (checked) {
  125. if (l_idx == -1) {
  126. f_lang_all.append(lang);
  127. }
  128. } else {
  129. if (l_idx != -1) {
  130. f_lang_all.remove(l_idx);
  131. }
  132. }
  133. f_lang_all.sort();
  134. undo_redo->create_action(TTR("Changed Locale Language Filter"));
  135. undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/language_filter", f_lang_all);
  136. undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/language_filter", prev);
  137. undo_redo->commit_action();
  138. }
  139. void EditorLocaleDialog::_filter_script_option_changed() {
  140. TreeItem *t = script_list->get_edited();
  141. String script = t->get_metadata(0);
  142. bool checked = t->is_checked(0);
  143. Variant prev;
  144. Array f_script_all;
  145. if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/script_filter")) {
  146. f_script_all = ProjectSettings::get_singleton()->get("internationalization/locale/script_filter");
  147. prev = f_script_all;
  148. }
  149. int l_idx = f_script_all.find(script);
  150. if (checked) {
  151. if (l_idx == -1) {
  152. f_script_all.append(script);
  153. }
  154. } else {
  155. if (l_idx != -1) {
  156. f_script_all.remove(l_idx);
  157. }
  158. }
  159. f_script_all.sort();
  160. undo_redo->create_action(TTR("Changed Locale Script Filter"));
  161. undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/script_filter", f_script_all);
  162. undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/script_filter", prev);
  163. undo_redo->commit_action();
  164. }
  165. void EditorLocaleDialog::_filter_cnt_option_changed() {
  166. TreeItem *t = cnt_list->get_edited();
  167. String cnt = t->get_metadata(0);
  168. bool checked = t->is_checked(0);
  169. Variant prev;
  170. Array f_cnt_all;
  171. if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/country_filter")) {
  172. f_cnt_all = ProjectSettings::get_singleton()->get("internationalization/locale/country_filter");
  173. prev = f_cnt_all;
  174. }
  175. int l_idx = f_cnt_all.find(cnt);
  176. if (checked) {
  177. if (l_idx == -1) {
  178. f_cnt_all.append(cnt);
  179. }
  180. } else {
  181. if (l_idx != -1) {
  182. f_cnt_all.remove(l_idx);
  183. }
  184. }
  185. f_cnt_all.sort();
  186. undo_redo->create_action(TTR("Changed Locale Country Filter"));
  187. undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/country_filter", f_cnt_all);
  188. undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/country_filter", prev);
  189. undo_redo->commit_action();
  190. }
  191. void EditorLocaleDialog::_filter_mode_changed(int p_mode) {
  192. int f_mode = filter_mode->get_selected_id();
  193. Variant prev;
  194. if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/locale_filter_mode")) {
  195. prev = ProjectSettings::get_singleton()->get("internationalization/locale/locale_filter_mode");
  196. }
  197. undo_redo->create_action(TTR("Changed Locale Filter Mode"));
  198. undo_redo->add_do_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter_mode", f_mode);
  199. undo_redo->add_undo_property(ProjectSettings::get_singleton(), "internationalization/locale/locale_filter_mode", prev);
  200. undo_redo->commit_action();
  201. _update_tree();
  202. }
  203. void EditorLocaleDialog::_edit_filters(bool p_checked) {
  204. _update_tree();
  205. }
  206. void EditorLocaleDialog::_update_tree() {
  207. updating_lists = true;
  208. int filter = SHOW_ALL_LOCALES;
  209. if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/locale_filter_mode")) {
  210. filter = ProjectSettings::get_singleton()->get("internationalization/locale/locale_filter_mode");
  211. }
  212. Array f_lang_all;
  213. if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/language_filter")) {
  214. f_lang_all = ProjectSettings::get_singleton()->get("internationalization/locale/language_filter");
  215. }
  216. Array f_cnt_all;
  217. if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/country_filter")) {
  218. f_cnt_all = ProjectSettings::get_singleton()->get("internationalization/locale/country_filter");
  219. }
  220. Array f_script_all;
  221. if (ProjectSettings::get_singleton()->has_setting("internationalization/locale/script_filter")) {
  222. f_script_all = ProjectSettings::get_singleton()->get("internationalization/locale/script_filter");
  223. }
  224. bool is_edit_mode = edit_filters->is_pressed();
  225. filter_mode->select(filter);
  226. // Hide text advanced edit and disable OK button if in filter edit mode.
  227. advanced->set_visible(!is_edit_mode);
  228. hb_locale->set_visible(!is_edit_mode && advanced->is_pressed());
  229. vb_script_list->set_visible(advanced->is_pressed());
  230. get_ok()->set_disabled(is_edit_mode);
  231. // Update language list.
  232. lang_list->clear();
  233. TreeItem *l_root = lang_list->create_item(nullptr);
  234. lang_list->set_hide_root(true);
  235. Vector<String> languages = TranslationServer::get_singleton()->get_all_languages();
  236. for (int i = 0; i < languages.size(); i++) {
  237. if (is_edit_mode || (filter == SHOW_ALL_LOCALES) || f_lang_all.has(languages[i]) || f_lang_all.empty()) {
  238. const String &lang = TranslationServer::get_singleton()->get_language_name(languages[i]);
  239. TreeItem *t = lang_list->create_item(l_root);
  240. if (is_edit_mode) {
  241. t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
  242. t->set_editable(0, true);
  243. t->set_checked(0, f_lang_all.has(languages[i]));
  244. } else if (lang_code->get_text() == languages[i]) {
  245. t->select(0);
  246. }
  247. t->set_text(0, vformat("%s [%s]", lang, languages[i]));
  248. t->set_metadata(0, languages[i]);
  249. }
  250. }
  251. // Update script list.
  252. script_list->clear();
  253. TreeItem *s_root = script_list->create_item(nullptr);
  254. script_list->set_hide_root(true);
  255. if (!is_edit_mode) {
  256. TreeItem *t = script_list->create_item(s_root);
  257. t->set_text(0, "[Default]");
  258. t->set_metadata(0, "");
  259. }
  260. Vector<String> scripts = TranslationServer::get_singleton()->get_all_scripts();
  261. for (int i = 0; i < scripts.size(); i++) {
  262. if (is_edit_mode || (filter == SHOW_ALL_LOCALES) || f_script_all.has(scripts[i]) || f_script_all.empty()) {
  263. const String &script = TranslationServer::get_singleton()->get_script_name(scripts[i]);
  264. TreeItem *t = script_list->create_item(s_root);
  265. if (is_edit_mode) {
  266. t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
  267. t->set_editable(0, true);
  268. t->set_checked(0, f_script_all.has(scripts[i]));
  269. } else if (script_code->get_text() == scripts[i]) {
  270. t->select(0);
  271. }
  272. t->set_text(0, vformat("%s [%s]", script, scripts[i]));
  273. t->set_metadata(0, scripts[i]);
  274. }
  275. }
  276. // Update country list.
  277. cnt_list->clear();
  278. TreeItem *c_root = cnt_list->create_item(nullptr);
  279. cnt_list->set_hide_root(true);
  280. if (!is_edit_mode) {
  281. TreeItem *t = cnt_list->create_item(c_root);
  282. t->set_text(0, "[Default]");
  283. t->set_metadata(0, "");
  284. }
  285. Vector<String> countries = TranslationServer::get_singleton()->get_all_countries();
  286. for (int i = 0; i < countries.size(); i++) {
  287. if (is_edit_mode || (filter == SHOW_ALL_LOCALES) || f_cnt_all.has(countries[i]) || f_cnt_all.empty()) {
  288. const String &cnt = TranslationServer::get_singleton()->get_country_name(countries[i]);
  289. TreeItem *t = cnt_list->create_item(c_root);
  290. if (is_edit_mode) {
  291. t->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
  292. t->set_editable(0, true);
  293. t->set_checked(0, f_cnt_all.has(countries[i]));
  294. } else if (country_code->get_text() == countries[i]) {
  295. t->select(0);
  296. }
  297. t->set_text(0, vformat("%s [%s]", cnt, countries[i]));
  298. t->set_metadata(0, countries[i]);
  299. }
  300. }
  301. updating_lists = false;
  302. }
  303. void EditorLocaleDialog::set_locale(const String &p_locale) {
  304. const String &locale = TranslationServer::get_singleton()->standardize_locale(p_locale);
  305. if (locale.empty()) {
  306. locale_set = false;
  307. lang_code->set_text("");
  308. script_code->set_text("");
  309. country_code->set_text("");
  310. variant_code->set_text("");
  311. } else {
  312. locale_set = true;
  313. Vector<String> locale_elements = p_locale.split("_");
  314. lang_code->set_text(locale_elements[0]);
  315. if (locale_elements.size() >= 2) {
  316. if (locale_elements[1].length() == 4 && is_ascii_upper_case(locale_elements[1][0]) && is_ascii_lower_case(locale_elements[1][1]) && is_ascii_lower_case(locale_elements[1][2]) && is_ascii_lower_case(locale_elements[1][3])) {
  317. script_code->set_text(locale_elements[1]);
  318. advanced->set_pressed(true);
  319. }
  320. if (locale_elements[1].length() == 2 && is_ascii_upper_case(locale_elements[1][0]) && is_ascii_upper_case(locale_elements[1][1])) {
  321. country_code->set_text(locale_elements[1]);
  322. }
  323. }
  324. if (locale_elements.size() >= 3) {
  325. if (locale_elements[2].length() == 2 && is_ascii_upper_case(locale_elements[2][0]) && is_ascii_upper_case(locale_elements[2][1])) {
  326. country_code->set_text(locale_elements[2]);
  327. } else {
  328. variant_code->set_text(locale_elements[2].to_lower());
  329. advanced->set_pressed(true);
  330. }
  331. }
  332. if (locale_elements.size() >= 4) {
  333. variant_code->set_text(locale_elements[3].to_lower());
  334. advanced->set_pressed(true);
  335. }
  336. }
  337. }
  338. void EditorLocaleDialog::popup_locale_dialog() {
  339. popup_centered_clamped(Size2(1050, 700) * EDSCALE, 0.8);
  340. }
  341. EditorLocaleDialog::EditorLocaleDialog() {
  342. undo_redo = EditorNode::get_undo_redo();
  343. set_title(TTR("Select a Locale"));
  344. VBoxContainer *vb = memnew(VBoxContainer);
  345. {
  346. HBoxContainer *hb_filter = memnew(HBoxContainer);
  347. {
  348. filter_mode = memnew(OptionButton);
  349. filter_mode->add_item(TTR("Show All Locales"), SHOW_ALL_LOCALES);
  350. filter_mode->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  351. filter_mode->add_item(TTR("Show Selected Locales Only"), SHOW_ONLY_SELECTED_LOCALES);
  352. filter_mode->select(0);
  353. filter_mode->connect("item_selected", this, "_filter_mode_changed");
  354. hb_filter->add_child(filter_mode);
  355. }
  356. {
  357. edit_filters = memnew(CheckButton);
  358. edit_filters->set_text("Edit Filters");
  359. edit_filters->set_toggle_mode(true);
  360. edit_filters->set_pressed(false);
  361. edit_filters->connect("toggled", this, "_edit_filters");
  362. hb_filter->add_child(edit_filters);
  363. }
  364. {
  365. advanced = memnew(CheckButton);
  366. advanced->set_text("Advanced");
  367. advanced->set_toggle_mode(true);
  368. advanced->set_pressed(false);
  369. advanced->connect("toggled", this, "_toggle_advanced");
  370. hb_filter->add_child(advanced);
  371. }
  372. vb->add_child(hb_filter);
  373. }
  374. {
  375. HBoxContainer *hb_lists = memnew(HBoxContainer);
  376. hb_lists->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  377. {
  378. VBoxContainer *vb_lang_list = memnew(VBoxContainer);
  379. vb_lang_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  380. {
  381. Label *lang_lbl = memnew(Label);
  382. lang_lbl->set_text(TTR("Language:"));
  383. vb_lang_list->add_child(lang_lbl);
  384. }
  385. {
  386. lang_list = memnew(Tree);
  387. lang_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  388. lang_list->connect("cell_selected", this, "_item_selected");
  389. lang_list->set_columns(1);
  390. lang_list->connect("item_edited", this, "_filter_lang_option_changed");
  391. vb_lang_list->add_child(lang_list);
  392. }
  393. hb_lists->add_child(vb_lang_list);
  394. }
  395. {
  396. vb_script_list = memnew(VBoxContainer);
  397. vb_script_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  398. {
  399. Label *script_lbl = memnew(Label);
  400. script_lbl->set_text(TTR("Script:"));
  401. vb_script_list->add_child(script_lbl);
  402. }
  403. {
  404. script_list = memnew(Tree);
  405. script_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  406. script_list->connect("cell_selected", this, "_item_selected");
  407. script_list->set_columns(1);
  408. script_list->connect("item_edited", this, "_filter_script_option_changed");
  409. vb_script_list->add_child(script_list);
  410. }
  411. hb_lists->add_child(vb_script_list);
  412. }
  413. {
  414. VBoxContainer *vb_cnt_list = memnew(VBoxContainer);
  415. vb_cnt_list->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  416. {
  417. Label *cnt_lbl = memnew(Label);
  418. cnt_lbl->set_text(TTR("Country:"));
  419. vb_cnt_list->add_child(cnt_lbl);
  420. }
  421. {
  422. cnt_list = memnew(Tree);
  423. cnt_list->set_v_size_flags(Control::SIZE_EXPAND_FILL);
  424. cnt_list->connect("cell_selected", this, "_item_selected");
  425. cnt_list->set_columns(1);
  426. cnt_list->connect("item_edited", this, "_filter_cnt_option_changed");
  427. vb_cnt_list->add_child(cnt_list);
  428. }
  429. hb_lists->add_child(vb_cnt_list);
  430. }
  431. vb->add_child(hb_lists);
  432. }
  433. {
  434. hb_locale = memnew(HBoxContainer);
  435. hb_locale->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  436. {
  437. {
  438. VBoxContainer *vb_language = memnew(VBoxContainer);
  439. vb_language->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  440. {
  441. Label *language_lbl = memnew(Label);
  442. language_lbl->set_text(TTR("Language"));
  443. vb_language->add_child(language_lbl);
  444. }
  445. {
  446. lang_code = memnew(LineEdit);
  447. lang_code->set_max_length(3);
  448. lang_code->set_tooltip("Language");
  449. vb_language->add_child(lang_code);
  450. }
  451. hb_locale->add_child(vb_language);
  452. }
  453. {
  454. VBoxContainer *vb_script = memnew(VBoxContainer);
  455. vb_script->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  456. {
  457. Label *script_lbl = memnew(Label);
  458. script_lbl->set_text(TTR("Script"));
  459. vb_script->add_child(script_lbl);
  460. }
  461. {
  462. script_code = memnew(LineEdit);
  463. script_code->set_max_length(4);
  464. script_code->set_tooltip("Script");
  465. vb_script->add_child(script_code);
  466. }
  467. hb_locale->add_child(vb_script);
  468. }
  469. {
  470. VBoxContainer *vb_country = memnew(VBoxContainer);
  471. vb_country->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  472. {
  473. Label *country_lbl = memnew(Label);
  474. country_lbl->set_text(TTR("Country"));
  475. vb_country->add_child(country_lbl);
  476. }
  477. {
  478. country_code = memnew(LineEdit);
  479. country_code->set_max_length(2);
  480. country_code->set_tooltip("Country");
  481. vb_country->add_child(country_code);
  482. }
  483. hb_locale->add_child(vb_country);
  484. }
  485. {
  486. VBoxContainer *vb_variant = memnew(VBoxContainer);
  487. vb_variant->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  488. {
  489. Label *variant_lbl = memnew(Label);
  490. variant_lbl->set_text(TTR("Variant"));
  491. vb_variant->add_child(variant_lbl);
  492. }
  493. {
  494. variant_code = memnew(LineEdit);
  495. variant_code->set_h_size_flags(Control::SIZE_EXPAND_FILL);
  496. variant_code->set_placeholder("Variant");
  497. variant_code->set_tooltip("Variant");
  498. vb_variant->add_child(variant_code);
  499. }
  500. hb_locale->add_child(vb_variant);
  501. }
  502. }
  503. vb->add_child(hb_locale);
  504. }
  505. add_child(vb);
  506. _update_tree();
  507. get_ok()->set_text(TTR("Select"));
  508. }