Sfoglia il codice sorgente

Merge pull request #104061 from a-johnston/better_no_query_handling

Improve default/no query quick open dialog behavior
Rémi Verschelde 5 mesi fa
parent
commit
1298e7078d

+ 60 - 31
editor/gui/editor_quick_open_dialog.cpp

@@ -373,12 +373,36 @@ void QuickOpenResultContainer::init(const Vector<StringName> &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<String, FilepathComparator> 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<QuickOpenResultCandidate> *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<QuickOpenResultCandidate> *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<QuickOpenResultCandidate> *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<QuickOpenResultCandidate> *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<StringName> &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) {

+ 3 - 2
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<FuzzySearchResult> search_results;
@@ -116,13 +115,13 @@ private:
 	Vector<QuickOpenResultCandidate> candidates;
 
 	OAHashMap<StringName, Vector<QuickOpenResultCandidate>> selected_history;
+	HashSet<String> 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<ConfigFile> history_file;
 
@@ -148,9 +147,11 @@ private:
 	static QuickOpenDisplayMode get_adaptive_display_mode(const Vector<StringName> &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<QuickOpenResultCandidate> *_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();