diff --git a/doc/classes/EditorFileDialog.xml b/doc/classes/EditorFileDialog.xml index d5c2ed55d75..1ac79d0e0ed 100644 --- a/doc/classes/EditorFileDialog.xml +++ b/doc/classes/EditorFileDialog.xml @@ -37,12 +37,24 @@ Adds the given [param menu] to the side of the file dialog with the given [param title] text on top. Only one side menu is allowed. + + + + Clear the filter for file names. + + Removes all filters except for "All Files (*)". + + + + Returns the value of the filter for file names. + + @@ -96,6 +108,13 @@ Shows the [EditorFileDialog] at the default size and position for file dialogs in the editor, and selects the file name if there is a current file. + + + + + Sets the value of the filter for file names. + + @@ -168,6 +187,12 @@ Emitted when a file is selected. + + + + Emitted when the filter for file names changes. + + diff --git a/editor/gui/editor_file_dialog.cpp b/editor/gui/editor_file_dialog.cpp index 77d0ba7a60a..bf21e562bd8 100644 --- a/editor/gui/editor_file_dialog.cpp +++ b/editor/gui/editor_file_dialog.cpp @@ -175,6 +175,7 @@ void EditorFileDialog::_update_theme_item_cache() { theme_cache.back_folder = get_editor_theme_icon(SNAME("Back")); theme_cache.reload = get_editor_theme_icon(SNAME("Reload")); theme_cache.toggle_hidden = get_editor_theme_icon(SNAME("GuiVisibilityVisible")); + theme_cache.toggle_filename_filter = get_editor_theme_icon(SNAME("FilenameFilter")); theme_cache.favorite = get_editor_theme_icon(SNAME("Favorites")); theme_cache.mode_thumbnails = get_editor_theme_icon(SNAME("FileThumbnail")); theme_cache.mode_list = get_editor_theme_icon(SNAME("FileList")); @@ -329,6 +330,7 @@ void EditorFileDialog::shortcut_input(const Ref &p_event) { handled = true; } if (ED_IS_SHORTCUT("file_dialog/focus_filter", p_event)) { + show_search_filter_button->set_pressed(!show_search_filter_button->is_pressed()); _focus_filter_box(); handled = true; } @@ -1146,6 +1148,15 @@ void EditorFileDialog::_filter_selected(int) { update_file_list(); } +void EditorFileDialog::_search_filter_selected() { + Vector items = item_list->get_selected_items(); + if (!items.is_empty()) { + int index = items[0]; + file->set_text(item_list->get_item_text(index)); + file->emit_signal("text_submitted", file->get_text()); + } +} + void EditorFileDialog::update_filters() { filter->clear(); @@ -1187,6 +1198,23 @@ void EditorFileDialog::clear_filters() { invalidate(); } +void EditorFileDialog::clear_search_filter() { + set_search_filter(""); + update_search_filter_gui(); + invalidate(); +} + +void EditorFileDialog::update_search_filter_gui() { + filter_hb->set_visible(show_search_filter); + if (!show_search_filter) { + search_string.clear(); + } + if (filter_box->get_text() == search_string) { + return; + } + filter_box->set_text(search_string); +} + void EditorFileDialog::add_filter(const String &p_filter, const String &p_description) { if (p_description.is_empty()) { filters.push_back(p_filter); @@ -1206,10 +1234,24 @@ void EditorFileDialog::set_filters(const Vector &p_filters) { invalidate(); } +void EditorFileDialog::set_search_filter(const String &p_search_filter) { + if (search_string == p_search_filter) { + return; + } + search_string = p_search_filter; + update_search_filter_gui(); + emit_signal(SNAME("filename_filter_changed"), filter); + invalidate(); +} + Vector EditorFileDialog::get_filters() const { return filters; } +String EditorFileDialog::get_search_filter() const { + return search_string; +} + String EditorFileDialog::get_current_dir() const { return dir_access->get_current_dir(); } @@ -1392,6 +1434,11 @@ void EditorFileDialog::_focus_filter_box() { void EditorFileDialog::_filter_changed(const String &p_text) { search_string = p_text; invalidate(); + + item_list->deselect_all(); + if (item_list->get_item_count() > 0) { + item_list->call_deferred("select", 0); + } } void EditorFileDialog::_file_sort_popup(int p_id) { @@ -1492,6 +1539,7 @@ void EditorFileDialog::_update_icons() { favorite->set_icon(theme_cache.favorite); show_hidden->set_icon(theme_cache.toggle_hidden); makedir->set_icon(theme_cache.create_folder); + show_search_filter_button->set_icon(theme_cache.toggle_filename_filter); filter_box->set_right_icon(theme_cache.filter_box); file_sort_button->set_icon(theme_cache.file_sort_button); @@ -1972,6 +2020,9 @@ void EditorFileDialog::_bind_methods() { ClassDB::bind_method(D_METHOD("get_option_count"), &EditorFileDialog::get_option_count); ClassDB::bind_method(D_METHOD("add_option", "name", "values", "default_value_index"), &EditorFileDialog::add_option); ClassDB::bind_method(D_METHOD("get_selected_options"), &EditorFileDialog::get_selected_options); + ClassDB::bind_method(D_METHOD("clear_filename_filter"), &EditorFileDialog::clear_search_filter); + ClassDB::bind_method(D_METHOD("set_filename_filter", "filter"), &EditorFileDialog::set_search_filter); + ClassDB::bind_method(D_METHOD("get_filename_filter"), &EditorFileDialog::get_search_filter); ClassDB::bind_method(D_METHOD("get_current_dir"), &EditorFileDialog::get_current_dir); ClassDB::bind_method(D_METHOD("get_current_file"), &EditorFileDialog::get_current_file); ClassDB::bind_method(D_METHOD("get_current_path"), &EditorFileDialog::get_current_path); @@ -2000,6 +2051,7 @@ void EditorFileDialog::_bind_methods() { ADD_SIGNAL(MethodInfo("file_selected", PropertyInfo(Variant::STRING, "path"))); ADD_SIGNAL(MethodInfo("files_selected", PropertyInfo(Variant::PACKED_STRING_ARRAY, "paths"))); ADD_SIGNAL(MethodInfo("dir_selected", PropertyInfo(Variant::STRING, "dir"))); + ADD_SIGNAL(MethodInfo("filename_filter_changed", PropertyInfo(Variant::STRING, "filter"))); ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"), "set_access", "get_access"); ADD_PROPERTY(PropertyInfo(Variant::INT, "display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List"), "set_display_mode", "get_display_mode"); @@ -2046,6 +2098,24 @@ void EditorFileDialog::set_show_hidden_files(bool p_show) { invalidate(); } +void EditorFileDialog::set_show_search_filter(bool p_show) { + if (p_show == show_search_filter) { + return; + } + if (p_show) { + filter_box->grab_focus(); + } else { + search_string.clear(); + filter_box->clear(); + if (filter_box->has_focus()) { + item_list->call_deferred("grab_focus"); + } + } + show_search_filter = p_show; + update_search_filter_gui(); + invalidate(); +} + bool EditorFileDialog::is_showing_hidden_files() const { return show_hidden_files; } @@ -2189,7 +2259,6 @@ EditorFileDialog::EditorFileDialog() { dir = memnew(LineEdit); dir->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE); pathhb->add_child(dir); - dir->set_h_size_flags(Control::SIZE_EXPAND_FILL); refresh = memnew(Button); refresh->set_theme_type_variation("FlatButton"); @@ -2204,37 +2273,6 @@ EditorFileDialog::EditorFileDialog() { favorite->connect(SceneStringName(pressed), callable_mp(this, &EditorFileDialog::_favorite_pressed)); pathhb->add_child(favorite); - show_hidden = memnew(Button); - show_hidden->set_theme_type_variation("FlatButton"); - show_hidden->set_toggle_mode(true); - show_hidden->set_pressed(is_showing_hidden_files()); - show_hidden->set_tooltip_text(TTR("Toggle the visibility of hidden files.")); - show_hidden->connect(SceneStringName(toggled), callable_mp(this, &EditorFileDialog::set_show_hidden_files)); - pathhb->add_child(show_hidden); - - pathhb->add_child(memnew(VSeparator)); - - Ref view_mode_group; - view_mode_group.instantiate(); - - mode_thumbnails = memnew(Button); - mode_thumbnails->set_theme_type_variation("FlatButton"); - mode_thumbnails->connect(SceneStringName(pressed), callable_mp(this, &EditorFileDialog::set_display_mode).bind(DISPLAY_THUMBNAILS)); - mode_thumbnails->set_toggle_mode(true); - mode_thumbnails->set_pressed(display_mode == DISPLAY_THUMBNAILS); - mode_thumbnails->set_button_group(view_mode_group); - mode_thumbnails->set_tooltip_text(TTR("View items as a grid of thumbnails.")); - pathhb->add_child(mode_thumbnails); - - mode_list = memnew(Button); - mode_list->set_theme_type_variation("FlatButton"); - mode_list->connect(SceneStringName(pressed), callable_mp(this, &EditorFileDialog::set_display_mode).bind(DISPLAY_LIST)); - mode_list->set_toggle_mode(true); - mode_list->set_pressed(display_mode == DISPLAY_LIST); - mode_list->set_button_group(view_mode_group); - mode_list->set_tooltip_text(TTR("View items as a list.")); - pathhb->add_child(mode_list); - shortcuts_container = memnew(HBoxContainer); pathhb->add_child(shortcuts_container); @@ -2250,6 +2288,8 @@ EditorFileDialog::EditorFileDialog() { makedir->connect(SceneStringName(pressed), callable_mp(this, &EditorFileDialog::_make_dir)); pathhb->add_child(makedir); + dir->set_h_size_flags(Control::SIZE_EXPAND_FILL); + body_hsplit = memnew(HSplitContainer); body_hsplit->set_v_size_flags(Control::SIZE_EXPAND_FILL); vbc->add_child(body_hsplit); @@ -2319,21 +2359,55 @@ EditorFileDialog::EditorFileDialog() { l = memnew(Label(TTR("Directories & Files:"))); l->set_theme_type_variation("HeaderSmall"); + l->set_h_size_flags(Control::SIZE_EXPAND_FILL); + lower_hb->add_child(l); - list_vb->add_child(lower_hb); - preview_hb->add_child(list_vb); + show_hidden = memnew(Button); + show_hidden->set_theme_type_variation("FlatButton"); + show_hidden->set_toggle_mode(true); + show_hidden->set_pressed(is_showing_hidden_files()); + show_hidden->set_tooltip_text(TTR("Toggle the visibility of hidden files.")); + show_hidden->connect(SceneStringName(toggled), callable_mp(this, &EditorFileDialog::set_show_hidden_files)); + lower_hb->add_child(show_hidden); - filter_box = memnew(LineEdit); - filter_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); - filter_box->set_placeholder(TTR("Filter")); - filter_box->connect(SceneStringName(text_changed), callable_mp(this, &EditorFileDialog::_filter_changed)); - lower_hb->add_child(filter_box); + lower_hb->add_child(memnew(VSeparator)); + + Ref view_mode_group; + view_mode_group.instantiate(); + + mode_thumbnails = memnew(Button); + mode_thumbnails->set_theme_type_variation("FlatButton"); + mode_thumbnails->connect(SceneStringName(pressed), callable_mp(this, &EditorFileDialog::set_display_mode).bind(DISPLAY_THUMBNAILS)); + mode_thumbnails->set_toggle_mode(true); + mode_thumbnails->set_pressed(display_mode == DISPLAY_THUMBNAILS); + mode_thumbnails->set_button_group(view_mode_group); + mode_thumbnails->set_tooltip_text(TTR("View items as a grid of thumbnails.")); + lower_hb->add_child(mode_thumbnails); + + mode_list = memnew(Button); + mode_list->set_theme_type_variation("FlatButton"); + mode_list->connect(SceneStringName(pressed), callable_mp(this, &EditorFileDialog::set_display_mode).bind(DISPLAY_LIST)); + mode_list->set_toggle_mode(true); + mode_list->set_pressed(display_mode == DISPLAY_LIST); + mode_list->set_button_group(view_mode_group); + mode_list->set_tooltip_text(TTR("View items as a list.")); + lower_hb->add_child(mode_list); + + lower_hb->add_child(memnew(VSeparator)); file_sort_button = memnew(MenuButton); file_sort_button->set_flat(true); file_sort_button->set_tooltip_text(TTR("Sort files")); + show_search_filter_button = memnew(Button); + show_search_filter_button->set_theme_type_variation("FlatButton"); + show_search_filter_button->set_toggle_mode(true); + show_search_filter_button->set_pressed(false); + show_search_filter_button->set_tooltip_text(TTR("Toggle the visibility of the filter for file names.")); + show_search_filter_button->connect("toggled", callable_mp(this, &EditorFileDialog::set_show_search_filter)); + lower_hb->add_child(show_search_filter_button); + PopupMenu *p = file_sort_button->get_popup(); p->connect(SceneStringName(id_pressed), callable_mp(this, &EditorFileDialog::_file_sort_popup)); p->add_radio_check_item(TTR("Sort by Name (Ascending)"), static_cast(FileSortOption::FILE_SORT_NAME)); @@ -2345,6 +2419,9 @@ EditorFileDialog::EditorFileDialog() { p->set_item_checked(0, true); lower_hb->add_child(file_sort_button); + list_vb->add_child(lower_hb); + preview_hb->add_child(list_vb); + // Item (files and folders) list with context menu. item_list = memnew(ItemList); @@ -2370,6 +2447,15 @@ EditorFileDialog::EditorFileDialog() { prev_cc->add_child(preview); preview_vb->hide(); + filter_hb = memnew(HBoxContainer); + filter_hb->add_child(memnew(Label(RTR("Filter:")))); + filter_box = memnew(LineEdit); + filter_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); + filter_box->set_placeholder(TTR("Filter")); + filter_hb->add_child(filter_box); + filter_hb->set_visible(false); + item_vb->add_child(filter_hb); + file_box = memnew(HBoxContainer); l = memnew(Label(TTR("File:"))); @@ -2398,6 +2484,8 @@ EditorFileDialog::EditorFileDialog() { item_list->connect("item_activated", callable_mp(this, &EditorFileDialog::_item_dc_selected).bind()); item_list->connect("empty_clicked", callable_mp(this, &EditorFileDialog::_items_clear_selection)); dir->connect("text_submitted", callable_mp(this, &EditorFileDialog::_dir_submitted)); + filter_box->connect(SceneStringName(text_changed), callable_mp(this, &EditorFileDialog::_filter_changed)); + filter_box->connect(SceneStringName(text_submitted), callable_mp(this, &EditorFileDialog::_search_filter_selected).unbind(1)); file->connect("text_submitted", callable_mp(this, &EditorFileDialog::_file_submitted)); filter->connect(SceneStringName(item_selected), callable_mp(this, &EditorFileDialog::_filter_selected)); diff --git a/editor/gui/editor_file_dialog.h b/editor/gui/editor_file_dialog.h index 1922155133b..a8032676601 100644 --- a/editor/gui/editor_file_dialog.h +++ b/editor/gui/editor_file_dialog.h @@ -128,8 +128,11 @@ private: Button *refresh = nullptr; Button *favorite = nullptr; Button *show_hidden = nullptr; + Button *show_search_filter_button = nullptr; String search_string; + bool show_search_filter = false; + HBoxContainer *filter_hb = nullptr; LineEdit *filter_box = nullptr; FileSortOption file_sort = FileSortOption::FILE_SORT_NAME; MenuButton *file_sort_button = nullptr; @@ -165,6 +168,7 @@ private: Ref back_folder; Ref reload; Ref toggle_hidden; + Ref toggle_filename_filter; Ref favorite; Ref mode_thumbnails; Ref mode_list; @@ -206,6 +210,7 @@ private: void update_dir(); void update_file_name(); void update_file_list(); + void update_search_filter_gui(); void update_filters(); void _focus_file_text(); @@ -239,6 +244,7 @@ private: void _focus_filter_box(); void _filter_changed(const String &p_text); + void _search_filter_selected(); void _file_sort_popup(int p_id); void _delete_items(); @@ -301,6 +307,9 @@ public: void add_filter(const String &p_filter, const String &p_description = ""); void set_filters(const Vector &p_filters); Vector get_filters() const; + void clear_search_filter(); + void set_search_filter(const String &p_search_filter); + String get_search_filter() const; void set_enable_multiple_selection(bool p_enable); Vector get_selected_files() const; @@ -341,6 +350,7 @@ public: static void set_default_show_hidden_files(bool p_show); static void set_default_display_mode(DisplayMode p_mode); void set_show_hidden_files(bool p_show); + void set_show_search_filter(bool p_show); bool is_showing_hidden_files() const; void invalidate();