From ed4689c4ee837b726e2c8690edabeaf4fb6cb79b Mon Sep 17 00:00:00 2001 From: kobewi Date: Mon, 19 Jan 2026 14:43:01 +0100 Subject: [PATCH] Fix favorite files handling --- editor/docks/filesystem_dock.cpp | 8 +++----- editor/docks/filesystem_dock.h | 1 + editor/gui/editor_file_dialog.cpp | 30 ++++++++++++++++++++++++--- editor/settings/editor_settings.cpp | 32 ++++++++++++++++++++--------- editor/settings/editor_settings.h | 1 + scene/gui/file_dialog.cpp | 11 ++++++++++ scene/gui/file_dialog.h | 4 ++++ 7 files changed, 69 insertions(+), 18 deletions(-) diff --git a/editor/docks/filesystem_dock.cpp b/editor/docks/filesystem_dock.cpp index 674ef7f222..694fa38b28 100644 --- a/editor/docks/filesystem_dock.cpp +++ b/editor/docks/filesystem_dock.cpp @@ -409,6 +409,8 @@ void FileSystemDock::_update_tree(const Vector &p_uncollapsed_paths, boo } if (fav_changed) { EditorSettings::get_singleton()->set_favorites(favorite_paths); + // Setting favorites causes the tree to update, so continuing is redundant. + return; } Ref folder_icon = get_editor_theme_icon(SNAME("Folder")); @@ -2479,7 +2481,6 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected } } EditorSettings::get_singleton()->set_favorites(favorites_list); - _update_tree(get_uncollapsed_paths()); } break; case FILE_MENU_REMOVE_FAVORITE: { @@ -2489,10 +2490,6 @@ void FileSystemDock::_file_option(int p_option, const Vector &p_selected favorites_list.erase(p_selected[i]); } EditorSettings::get_singleton()->set_favorites(favorites_list); - _update_tree(get_uncollapsed_paths()); - if (current_path == "Favorites") { - _update_file_list(true); - } } break; case FILE_MENU_SHOW_IN_FILESYSTEM: { @@ -4553,6 +4550,7 @@ FileSystemDock::FileSystemDock() { file_list_display_mode = FILE_LIST_DISPLAY_THUMBNAILS; ProjectSettings::get_singleton()->connect("settings_changed", callable_mp(this, &FileSystemDock::_project_settings_changed)); + EditorSettings::get_singleton()->connect("_favorites_changed", callable_mp(this, &FileSystemDock::update_all)); main_scene_path = ResourceUID::ensure_path(GLOBAL_GET("application/run/main_scene")); add_resource_tooltip_plugin(memnew(EditorTextureTooltipPlugin)); diff --git a/editor/docks/filesystem_dock.h b/editor/docks/filesystem_dock.h index 36b48c115e..a7a3d64377 100644 --- a/editor/docks/filesystem_dock.h +++ b/editor/docks/filesystem_dock.h @@ -275,6 +275,7 @@ private: void _update_tree(const Vector &p_uncollapsed_paths = Vector(), bool p_uncollapse_root = false, bool p_scroll_to_selected = true); void _navigate_to_path(const String &p_path, bool p_select_in_favorites = false, bool p_grab_focus = false); bool _update_filtered_items(TreeItem *p_tree_item = nullptr); + void _append_favorite_items(); void _file_list_gui_input(Ref p_event); void _tree_gui_input(Ref p_event); diff --git a/editor/gui/editor_file_dialog.cpp b/editor/gui/editor_file_dialog.cpp index d035f17563..96a03a3d20 100644 --- a/editor/gui/editor_file_dialog.cpp +++ b/editor/gui/editor_file_dialog.cpp @@ -126,9 +126,33 @@ void EditorFileDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_VISIBILITY_CHANGED: { if (!is_visible()) { - // Synchronize back favorites and recent directories, in case they have changed. - EditorSettings::get_singleton()->set_favorites(get_favorite_list(), false); - EditorSettings::get_singleton()->set_recent_dirs(get_recent_list(), false); + // Synchronize back favorites and recent directories if they have changed. + if (favorites_changed) { + Vector settings_favorites = EditorSettings::get_singleton()->get_favorites(); + Vector current_favorites = get_favorite_list(); + LocalVector to_erase; + + // The favorite list in EditorSettings may have files in between. They need to be handled properly to preserve order. + for (const String &fav : settings_favorites) { + if (!fav.ends_with("/")) { + continue; + } + int64_t idx = current_favorites.find(fav); + if (idx == -1) { + to_erase.push_back(fav); + } else { + current_favorites.remove_at(idx); + } + } + for (const String &fav : to_erase) { + settings_favorites.erase(fav); + } + settings_favorites.append_array(current_favorites); + EditorSettings::get_singleton()->set_favorites(settings_favorites, false); + } + if (recents_changed) { + EditorSettings::get_singleton()->set_recent_dirs(get_recent_list(), false); + } } } break; diff --git a/editor/settings/editor_settings.cpp b/editor/settings/editor_settings.cpp index 5ddf60ab8b..0f381c0ff3 100644 --- a/editor/settings/editor_settings.cpp +++ b/editor/settings/editor_settings.cpp @@ -1595,13 +1595,11 @@ void EditorSettings::save_project_metadata() { } void EditorSettings::set_favorites(const Vector &p_favorites, bool p_update_file_dialog) { - if (p_update_file_dialog) { - FileDialog::set_favorite_list(p_favorites); - } else if (p_favorites == favorites) { - // If the list came from EditorFileDialog, it may be the same as before. - return; - } set_favorites_bind(p_favorites); + if (p_update_file_dialog) { + FileDialog::set_favorite_list(get_favorite_folders()); + } + emit_signal(SNAME("_favorites_changed")); } void EditorSettings::set_favorites_bind(const Vector &p_favorites) { @@ -1636,6 +1634,22 @@ Vector EditorSettings::get_favorites() const { return favorites; } +Vector EditorSettings::get_favorite_folders() const { + Vector folder_favorites; + folder_favorites.resize(favorites.size()); + String *folder_write = folder_favorites.ptrw(); + + int i = 0; + for (const String &fav : favorites) { + if (fav.ends_with("/")) { + folder_write[i] = fav; + i++; + } + } + folder_favorites.resize(i); + return folder_favorites; +} + HashMap EditorSettings::get_favorite_properties() const { return favorite_properties; } @@ -1643,9 +1657,6 @@ HashMap EditorSettings::get_favorite_properties() con void EditorSettings::set_recent_dirs(const Vector &p_recent_dirs, bool p_update_file_dialog) { if (p_update_file_dialog) { FileDialog::set_recent_list(p_recent_dirs); - } else if (p_recent_dirs == recent_dirs) { - // If the list came from EditorFileDialog, it may be the same as before. - return; } set_recent_dirs_bind(p_recent_dirs); } @@ -1694,7 +1705,7 @@ void EditorSettings::load_favorites_and_recent_dirs() { line = f->get_line().strip_edges(); } } - FileDialog::set_favorite_list(favorites); + FileDialog::set_favorite_list(get_favorite_folders()); /// Inspector Favorites @@ -2282,6 +2293,7 @@ void EditorSettings::_bind_methods() { ClassDB::bind_method(D_METHOD("mark_setting_changed", "setting"), &EditorSettings::mark_setting_changed); ADD_SIGNAL(MethodInfo("settings_changed")); + ADD_SIGNAL(MethodInfo("_favorites_changed")); BIND_CONSTANT(NOTIFICATION_EDITOR_SETTINGS_CHANGED); } diff --git a/editor/settings/editor_settings.h b/editor/settings/editor_settings.h index b36cb478f1..dcb6046304 100644 --- a/editor/settings/editor_settings.h +++ b/editor/settings/editor_settings.h @@ -180,6 +180,7 @@ public: void set_favorites(const Vector &p_favorites, bool p_update_file_dialog = true); void set_favorites_bind(const Vector &p_favorites); Vector get_favorites() const; + Vector get_favorite_folders() const; void set_favorite_properties(const HashMap &p_favorite_properties); HashMap get_favorite_properties() const; void set_recent_dirs(const Vector &p_recent_dirs, bool p_update_file_dialog = true); diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 57bc7a2d6e..70cf63f415 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -110,6 +110,11 @@ void FileDialog::_popup_base(const Rect2i &p_screen_rect) { } } +void FileDialog::_clear_changed_status() { + favorites_changed = false; + recents_changed = false; +} + void FileDialog::set_visible(bool p_visible) { if (p_visible) { _update_option_controls(); @@ -258,6 +263,8 @@ void FileDialog::_notification(int p_what) { _update_favorite_list(); _update_recent_list(); invalidate(); // Put it here to preview in the editor. + } else { + callable_mp(this, &FileDialog::_clear_changed_status).call_deferred(); } } break; @@ -1680,6 +1687,7 @@ void FileDialog::_favorite_pressed() { } else { global_favorites.push_back(directory); } + favorites_changed = true; _update_favorite_list(); } @@ -1696,6 +1704,7 @@ void FileDialog::_favorite_move_up() { return; } SWAP(global_favorites[a_idx], global_favorites[b_idx]); + favorites_changed = true; _update_favorite_list(); } @@ -1712,6 +1721,7 @@ void FileDialog::_favorite_move_down() { return; } SWAP(global_favorites[a_idx], global_favorites[b_idx]); + favorites_changed = true; _update_favorite_list(); } @@ -1811,6 +1821,7 @@ void FileDialog::_save_to_recent() { } } global_recents.insert(0, directory); + recents_changed = true; _update_recent_list(); } diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index 46dbbeb8f2..aa0582a40b 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -366,6 +366,9 @@ private: protected: Ref dir_access; + bool favorites_changed = false; + bool recents_changed = false; + bool _can_use_native_popup() const; virtual void _item_menu_id_pressed(int p_option); virtual void _dir_contents_changed() {} @@ -375,6 +378,7 @@ protected: virtual Color _get_folder_color(const String &p_path) const { return theme_cache.folder_icon_color; } virtual void _popup_base(const Rect2i &p_screen_rect = Rect2i()) override; + void _clear_changed_status(); void _validate_property(PropertyInfo &p_property) const; void _notification(int p_what);