From 163c8be88412e2ca22cb24efd1802f3bcb7e3002 Mon Sep 17 00:00:00 2001 From: Adam Johnston Date: Sun, 2 Mar 2025 16:13:28 -0800 Subject: [PATCH] Remove file limit for quick open window --- editor/gui/editor_quick_open_dialog.cpp | 91 ++++++++++++++++--------- editor/gui/editor_quick_open_dialog.h | 5 +- 2 files changed, 63 insertions(+), 33 deletions(-) diff --git a/editor/gui/editor_quick_open_dialog.cpp b/editor/gui/editor_quick_open_dialog.cpp index 40b2242f460..71b92045b28 100644 --- a/editor/gui/editor_quick_open_dialog.cpp +++ b/editor/gui/editor_quick_open_dialog.cpp @@ -373,12 +373,36 @@ void QuickOpenResultContainer::init(const Vector &p_base_types) { _create_initial_results(); } +void QuickOpenResultContainer::_sort_filepaths(int p_max_results) { + struct FilepathComparator { + bool operator()(const String &p_lhs, const String &p_rhs) const { + // Sort on (length, alphanumeric) to prioritize shorter filepaths + return p_lhs.length() == p_rhs.length() ? p_lhs < p_rhs : p_lhs.length() < p_rhs.length(); + } + }; + + SortArray sorter; + if (filepaths.size() > p_max_results) { + sorter.partial_sort(0, filepaths.size(), p_max_results, filepaths.ptrw()); + } else { + sorter.sort(filepaths.ptrw(), filepaths.size()); + } +} + void QuickOpenResultContainer::_create_initial_results() { file_type_icons.clear(); file_type_icons.insert(SNAME("__default_icon"), get_editor_theme_icon(SNAME("Object"))); filepaths.clear(); filetypes.clear(); + history_set.clear(); + Vector *history = _get_history(); + if (history) { + for (const QuickOpenResultCandidate &candidate : *history) { + history_set.insert(candidate.file_path); + } + } _find_filepaths_in_folder(EditorFileSystem::get_singleton()->get_filesystem(), include_addons_toggle->is_pressed()); + _sort_filepaths(result_items.size()); max_total_results = MIN(filepaths.size(), result_items.size()); update_results(); } @@ -416,25 +440,26 @@ void QuickOpenResultContainer::set_query_and_update(const String &p_query) { update_results(); } -void QuickOpenResultContainer::_setup_candidate(QuickOpenResultCandidate &p_candidate, const String &p_filepath) { - ResourceUID::ID id = EditorFileSystem::get_singleton()->get_file_uid(p_filepath); - if (id == ResourceUID::INVALID_ID) { - p_candidate.file_path = p_filepath; - } else { - p_candidate.file_path = ResourceUID::get_singleton()->id_to_text(id); +Vector *QuickOpenResultContainer::_get_history() { + if (base_types.size() == 1) { + return selected_history.lookup_ptr(base_types[0]); } - p_candidate.result = nullptr; + return nullptr; +} +void QuickOpenResultContainer::_setup_candidate(QuickOpenResultCandidate &p_candidate, const String &p_filepath) { + p_candidate.file_path = ResourceUID::ensure_path(p_filepath); + p_candidate.result = nullptr; StringName actual_type; { StringName *actual_type_ptr = filetypes.lookup_ptr(p_filepath); if (actual_type_ptr) { actual_type = *actual_type_ptr; } else { - ERR_PRINT(vformat("EditorQuickOpenDialog: No type for path %s.", p_filepath)); + ERR_PRINT(vformat("EditorQuickOpenDialog: No type for path %s.", p_candidate.file_path)); } } - EditorResourcePreview::PreviewItem item = EditorResourcePreview::get_singleton()->get_resource_preview_if_available(p_filepath); + EditorResourcePreview::PreviewItem item = EditorResourcePreview::get_singleton()->get_resource_preview_if_available(p_candidate.file_path); if (item.preview.is_valid()) { p_candidate.thumbnail = item.preview; } else if (file_type_icons.has(actual_type)) { @@ -453,7 +478,6 @@ void QuickOpenResultContainer::_setup_candidate(QuickOpenResultCandidate &p_cand } void QuickOpenResultContainer::update_results() { - showing_history = false; candidates.clear(); if (query.is_empty()) { _use_default_candidates(); @@ -464,17 +488,18 @@ void QuickOpenResultContainer::update_results() { } void QuickOpenResultContainer::_use_default_candidates() { - if (filepaths.size() <= SHOW_ALL_FILES_THRESHOLD) { - candidates.resize(filepaths.size()); - QuickOpenResultCandidate *candidates_write = candidates.ptrw(); - for (const String &filepath : filepaths) { - _setup_candidate(*candidates_write++, filepath); + Vector *history = _get_history(); + if (history) { + candidates.append_array(*history); + } + int count = candidates.size(); + candidates.resize(MIN(max_total_results, filepaths.size())); + for (const String &filepath : filepaths) { + if (count >= max_total_results) { + break; } - } else if (base_types.size() == 1) { - Vector *history = selected_history.lookup_ptr(base_types[0]); - if (history) { - showing_history = true; - candidates.append_array(*history); + if (!history || !history_set.has(filepath)) { + _setup_candidate(candidates.write[count++], filepath); } } } @@ -524,8 +549,6 @@ void QuickOpenResultContainer::_update_result_items(int p_new_visible_results_co if (!any_results) { if (filepaths.is_empty()) { no_results_label->set_text(TTR("No files found for this type")); - } else if (query.is_empty()) { - no_results_label->set_text(TTR("Start searching to find files...")); } else { no_results_label->set_text(TTR("No results found")); } @@ -621,7 +644,8 @@ void QuickOpenResultContainer::_select_item(int p_index) { } result_items[selection_index]->highlight_item(true); - file_details_path->set_text(get_selected() + (showing_history ? TTR(" (recently opened)") : "")); + bool in_history = history_set.has(candidates[selection_index].file_path); + file_details_path->set_text(get_selected() + (in_history ? TTR(" (recently opened)") : "")); const QuickOpenResultItem *item = result_items[selection_index]; @@ -727,7 +751,7 @@ bool QuickOpenResultContainer::has_nothing_selected() const { String QuickOpenResultContainer::get_selected() const { ERR_FAIL_COND_V_MSG(has_nothing_selected(), String(), "Tried to get selected file, but nothing was selected."); - return ResourceUID::ensure_path(candidates[selection_index].file_path); + return candidates[selection_index].file_path; } QuickOpenDisplayMode QuickOpenResultContainer::get_adaptive_display_mode(const Vector &p_base_types) { @@ -749,6 +773,11 @@ QuickOpenDisplayMode QuickOpenResultContainer::get_adaptive_display_mode(const V return QuickOpenDisplayMode::LIST; } +String _get_uid_string(const String &p_filepath) { + ResourceUID::ID id = EditorFileSystem::get_singleton()->get_file_uid(p_filepath); + return id == ResourceUID::INVALID_ID ? p_filepath : ResourceUID::get_singleton()->id_to_text(id); +} + void QuickOpenResultContainer::save_selected_item() { if (base_types.size() > 1) { // Getting the type of the file and checking which base type it belongs to should be possible. @@ -773,6 +802,7 @@ void QuickOpenResultContainer::save_selected_item() { } selected.result = nullptr; + history_set.insert(selected.file_path); type_history->insert(0, selected); if (type_history->size() > MAX_HISTORY_SIZE) { type_history->resize(MAX_HISTORY_SIZE); @@ -785,7 +815,7 @@ void QuickOpenResultContainer::save_selected_item() { int i = 0; for (const QuickOpenResultCandidate &candidate : *type_history) { - paths_write[i] = candidate.file_path; + paths_write[i] = _get_uid_string(candidate.file_path); i++; } } @@ -796,6 +826,7 @@ void QuickOpenResultContainer::save_selected_item() { void QuickOpenResultContainer::cleanup() { num_visible_results = 0; candidates.clear(); + history_set.clear(); _select_item(-1); for (QuickOpenResultItem *item : result_items) { @@ -981,9 +1012,8 @@ QuickOpenResultListItem::QuickOpenResultListItem() { void QuickOpenResultListItem::set_content(const QuickOpenResultCandidate &p_candidate, bool p_highlight) { thumbnail->set_texture(p_candidate.thumbnail); - const String file_path = ResourceUID::ensure_path(p_candidate.file_path); - name->set_text(file_path.get_file()); - path->set_text(file_path.get_base_dir()); + name->set_text(p_candidate.file_path.get_file()); + path->set_text(p_candidate.file_path.get_base_dir()); name->reset_highlights(); path->reset_highlights(); @@ -1053,9 +1083,8 @@ QuickOpenResultGridItem::QuickOpenResultGridItem() { void QuickOpenResultGridItem::set_content(const QuickOpenResultCandidate &p_candidate, bool p_highlight) { thumbnail->set_texture(p_candidate.thumbnail); - const String file_path = ResourceUID::ensure_path(p_candidate.file_path); - name->set_text(file_path.get_file()); - name->set_tooltip_text(file_path); + name->set_text(p_candidate.file_path.get_file()); + name->set_tooltip_text(p_candidate.file_path); name->reset_highlights(); if (p_highlight && p_candidate.result != nullptr) { diff --git a/editor/gui/editor_quick_open_dialog.h b/editor/gui/editor_quick_open_dialog.h index 9cffae5dc8d..a730e7921fb 100644 --- a/editor/gui/editor_quick_open_dialog.h +++ b/editor/gui/editor_quick_open_dialog.h @@ -106,7 +106,6 @@ protected: void _notification(int p_what); private: - static constexpr int SHOW_ALL_FILES_THRESHOLD = 30; static constexpr int MAX_HISTORY_SIZE = 20; Vector search_results; @@ -116,13 +115,13 @@ private: Vector candidates; OAHashMap> selected_history; + HashSet history_set; String query; int selection_index = -1; int num_visible_results = 0; int max_total_results = 0; - bool showing_history = false; bool never_opened = true; Ref history_file; @@ -148,9 +147,11 @@ private: static QuickOpenDisplayMode get_adaptive_display_mode(const Vector &p_base_types); void _ensure_result_vector_capacity(); + void _sort_filepaths(int p_max_results); void _create_initial_results(); void _find_filepaths_in_folder(EditorFileSystemDirectory *p_directory, bool p_include_addons); + Vector *_get_history(); void _setup_candidate(QuickOpenResultCandidate &p_candidate, const String &p_filepath); void _setup_candidate(QuickOpenResultCandidate &p_candidate, const FuzzySearchResult &p_result); void _update_fuzzy_search_results();