From 1f0f96e6d75f8e2f308bcd7766dc664d77062222 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Sun, 5 Mar 2023 15:30:36 +0000 Subject: [PATCH] CharacterMap: Limit the number of results from the GUI character search Past a few hundred matches, the search is no longer useful, and takes an excessive amount of time to recalculate the column widths by measuring thousands of pieces of text. 250 seems like a reasonable arbitrary limit, and keeps things nice and snappy. :^) --- .../Applications/CharacterMap/CMakeLists.txt | 1 + .../CharacterMap/CharacterSearchWidget.cpp | 7 ++++++ .../CharacterMap/SearchCharacters.cpp | 25 +++++++++++++++++++ .../CharacterMap/SearchCharacters.h | 21 +++------------- Userland/Applications/CharacterMap/main.cpp | 3 ++- 5 files changed, 39 insertions(+), 18 deletions(-) create mode 100644 Userland/Applications/CharacterMap/SearchCharacters.cpp diff --git a/Userland/Applications/CharacterMap/CMakeLists.txt b/Userland/Applications/CharacterMap/CMakeLists.txt index 03583a7525..c92ce2508a 100644 --- a/Userland/Applications/CharacterMap/CMakeLists.txt +++ b/Userland/Applications/CharacterMap/CMakeLists.txt @@ -10,6 +10,7 @@ compile_gml(CharacterSearchWindow.gml CharacterSearchWindowGML.h character_searc set(SOURCES CharacterMapWidget.cpp CharacterSearchWidget.cpp + SearchCharacters.cpp main.cpp ) diff --git a/Userland/Applications/CharacterMap/CharacterSearchWidget.cpp b/Userland/Applications/CharacterMap/CharacterSearchWidget.cpp index cc8b250d51..29e8736563 100644 --- a/Userland/Applications/CharacterMap/CharacterSearchWidget.cpp +++ b/Userland/Applications/CharacterMap/CharacterSearchWidget.cpp @@ -84,6 +84,7 @@ void CharacterSearchWidget::search() // TODO: Sort the results nicely. They're sorted by code-point for now, which is easy, but not the most useful. // Sorting intelligently in a style similar to Assistant would be nicer. + // Note that this will mean limiting the number of results some other way. auto& model = static_cast(*m_results_table->model()); model.clear(); auto query = m_search_input->text(); @@ -94,5 +95,11 @@ void CharacterSearchWidget::search() builder.append_code_point(code_point); model.add_result({ code_point, builder.to_deprecated_string(), move(display_name) }); + + // Stop when we reach 250 results. + // This is already too many for the search to be useful, and means we don't spend forever recalculating the column size. + if (model.row_count({}) >= 250) + return IterationDecision::Break; + return IterationDecision::Continue; }); } diff --git a/Userland/Applications/CharacterMap/SearchCharacters.cpp b/Userland/Applications/CharacterMap/SearchCharacters.cpp new file mode 100644 index 0000000000..ba359cf590 --- /dev/null +++ b/Userland/Applications/CharacterMap/SearchCharacters.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022-2023, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "SearchCharacters.h" +#include + +void for_each_character_containing(StringView query, Function callback) +{ + DeprecatedString uppercase_query = query.to_uppercase_string(); + StringView uppercase_query_view = uppercase_query.view(); + constexpr u32 maximum_code_point = 0x10FFFF; + // FIXME: There's probably a better way to do this than just looping, but it still only takes ~150ms to run for me! + for (u32 code_point = 1; code_point <= maximum_code_point; ++code_point) { + if (auto maybe_display_name = Unicode::code_point_display_name(code_point); maybe_display_name.has_value()) { + auto display_name = maybe_display_name.release_value(); + if (display_name.contains(uppercase_query_view, AK::CaseSensitivity::CaseSensitive)) { + if (callback(code_point, move(display_name)) == IterationDecision::Break) + break; + } + } + } +} diff --git a/Userland/Applications/CharacterMap/SearchCharacters.h b/Userland/Applications/CharacterMap/SearchCharacters.h index 50d2765879..209973d453 100644 --- a/Userland/Applications/CharacterMap/SearchCharacters.h +++ b/Userland/Applications/CharacterMap/SearchCharacters.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Sam Atkins + * Copyright (c) 2022-2023, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -7,20 +7,7 @@ #pragma once #include -#include +#include +#include -template -void for_each_character_containing(StringView query, Callback callback) -{ - DeprecatedString uppercase_query = query.to_uppercase_string(); - StringView uppercase_query_view = uppercase_query.view(); - constexpr u32 maximum_code_point = 0x10FFFF; - // FIXME: There's probably a better way to do this than just looping, but it still only takes ~150ms to run for me! - for (u32 code_point = 1; code_point <= maximum_code_point; ++code_point) { - if (auto maybe_display_name = Unicode::code_point_display_name(code_point); maybe_display_name.has_value()) { - auto display_name = maybe_display_name.release_value(); - if (display_name.contains(uppercase_query_view, AK::CaseSensitivity::CaseSensitive)) - callback(code_point, move(display_name)); - } - } -} +void for_each_character_containing(StringView query, Function callback); diff --git a/Userland/Applications/CharacterMap/main.cpp b/Userland/Applications/CharacterMap/main.cpp index 4b3bcb0171..7be95272da 100644 --- a/Userland/Applications/CharacterMap/main.cpp +++ b/Userland/Applications/CharacterMap/main.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Sam Atkins + * Copyright (c) 2022-2023, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -28,6 +28,7 @@ static void search_and_print_results(DeprecatedString const& query) builder.append(display_name); outln(builder.string_view()); result_count++; + return IterationDecision::Continue; }); if (result_count == 0)