editor_file_dialog.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /**************************************************************************/
  2. /* editor_file_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_file_dialog.h"
  31. #include "core/config/project_settings.h"
  32. #include "editor/docks/filesystem_dock.h"
  33. #include "editor/editor_string_names.h"
  34. #include "editor/file_system/dependency_editor.h"
  35. #include "editor/settings/editor_settings.h"
  36. #include "editor/themes/editor_scale.h"
  37. void EditorFileDialog::_item_menu_id_pressed(int p_option) {
  38. // Use dependency dialog to delete the entry in the editor, but only for project files.
  39. if (p_option == ITEM_MENU_DELETE && get_access() == ACCESS_RESOURCES) {
  40. const PackedInt32Array selected = get_file_item_list()->get_selected_items();
  41. if (selected.is_empty()) {
  42. return;
  43. }
  44. if (!dependency_remove_dialog) {
  45. dependency_remove_dialog = memnew(DependencyRemoveDialog);
  46. add_child(dependency_remove_dialog);
  47. }
  48. const Dictionary meta = get_file_item_list()->get_item_metadata(selected[0]);
  49. const String delete_path = dir_access->get_current_dir().path_join(meta["name"]);
  50. if (meta["dir"]) {
  51. dependency_remove_dialog->show(Vector<String>{ delete_path }, Vector<String>());
  52. } else {
  53. dependency_remove_dialog->show(Vector<String>(), Vector<String>{ delete_path });
  54. }
  55. return;
  56. }
  57. FileDialog::_item_menu_id_pressed(p_option);
  58. }
  59. bool EditorFileDialog::_should_use_native_popup() const {
  60. #ifdef ANDROID_ENABLED
  61. // Native file dialog on Android, returns a file URI instead of a path and does not support res://, user://, or options. This requires editor-side changes to handle properly, so disabling it for now.
  62. return false;
  63. #else
  64. return _can_use_native_popup() && (OS::get_singleton()->is_sandboxed() || EDITOR_GET("interface/editor/use_native_file_dialogs").operator bool());
  65. #endif
  66. }
  67. bool EditorFileDialog::_should_hide_file(const String &p_file) const {
  68. if (Engine::get_singleton()->is_project_manager_hint()) {
  69. return false;
  70. }
  71. const String full_path = dir_access->get_current_dir().path_join(p_file);
  72. return EditorFileSystem::_should_skip_directory(full_path);
  73. }
  74. Color EditorFileDialog::_get_folder_color(const String &p_path) const {
  75. return FileSystemDock::get_dir_icon_color(p_path, FileDialog::_get_folder_color(p_path));
  76. }
  77. Vector2i EditorFileDialog::_get_list_mode_icon_size() const {
  78. return Vector2i();
  79. }
  80. void EditorFileDialog::_bind_methods() {
  81. #ifndef DISABLE_DEPRECATED
  82. ClassDB::bind_method(D_METHOD("add_side_menu", "menu", "title"), &EditorFileDialog::add_side_menu, DEFVAL(""));
  83. ClassDB::bind_method(D_METHOD("set_disable_overwrite_warning", "disable"), &EditorFileDialog::set_disable_overwrite_warning);
  84. ClassDB::bind_method(D_METHOD("is_overwrite_warning_disabled"), &EditorFileDialog::is_overwrite_warning_disabled);
  85. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_overwrite_warning", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_disable_overwrite_warning", "is_overwrite_warning_disabled");
  86. #endif
  87. }
  88. void EditorFileDialog::_validate_property(PropertyInfo &p_property) const {
  89. // Hide properties controlled by editor settings.
  90. if (p_property.name == "use_native_dialog" || p_property.name == "show_hidden_files" || p_property.name == "display_mode") {
  91. p_property.usage = PROPERTY_USAGE_NONE;
  92. }
  93. }
  94. void EditorFileDialog::_dir_contents_changed() {
  95. if (!EditorFileSystem::get_singleton()) {
  96. return;
  97. }
  98. bool scan_required = false;
  99. switch (get_access()) {
  100. case FileDialog::ACCESS_RESOURCES: {
  101. scan_required = true;
  102. } break;
  103. case FileDialog::ACCESS_USERDATA: {
  104. // Directories within the project dir are unlikely to be accessed.
  105. } break;
  106. case FileDialog::ACCESS_FILESYSTEM: {
  107. // Directories within the project dir may still be accessed.
  108. const String localized_path = ProjectSettings::get_singleton()->localize_path(get_current_dir());
  109. scan_required = localized_path.is_resource_file();
  110. } break;
  111. }
  112. if (scan_required) {
  113. EditorFileSystem::get_singleton()->scan_changes();
  114. }
  115. }
  116. void EditorFileDialog::_notification(int p_what) {
  117. switch (p_what) {
  118. case NOTIFICATION_VISIBILITY_CHANGED: {
  119. if (!is_visible()) {
  120. // Synchronize back favorites and recent directories if they have changed.
  121. if (favorites_changed) {
  122. Vector<String> settings_favorites = EditorSettings::get_singleton()->get_favorites();
  123. Vector<String> current_favorites = get_favorite_list();
  124. LocalVector<String> to_erase;
  125. // The favorite list in EditorSettings may have files in between. They need to be handled properly to preserve order.
  126. for (const String &fav : settings_favorites) {
  127. if (!fav.ends_with("/")) {
  128. continue;
  129. }
  130. int64_t idx = current_favorites.find(fav);
  131. if (idx == -1) {
  132. to_erase.push_back(fav);
  133. } else {
  134. current_favorites.remove_at(idx);
  135. }
  136. }
  137. for (const String &fav : to_erase) {
  138. settings_favorites.erase(fav);
  139. }
  140. settings_favorites.append_array(current_favorites);
  141. EditorSettings::get_singleton()->set_favorites(settings_favorites, false);
  142. }
  143. if (recents_changed) {
  144. EditorSettings::get_singleton()->set_recent_dirs(get_recent_list(), false);
  145. }
  146. }
  147. } break;
  148. case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
  149. if (!EditorSettings::get_singleton()->check_changed_settings_in_group("filesystem/file_dialog")) {
  150. break;
  151. }
  152. set_show_hidden_files(EDITOR_GET("filesystem/file_dialog/show_hidden_files"));
  153. set_display_mode((DisplayMode)EDITOR_GET("filesystem/file_dialog/display_mode").operator int());
  154. } break;
  155. }
  156. }