diff options
author | Gary Kramlich <grim@reaperworld.com> | 2023-02-17 19:32:38 -0600 |
---|---|---|
committer | Gary Kramlich <grim@reaperworld.com> | 2023-02-17 19:32:38 -0600 |
commit | f543bef1f1b1cfd8bae65ebeb1bd63a4afc2a571 (patch) | |
tree | 2c367c3f8195e6a945525e95a46eb538b2927d83 /libpurple | |
parent | de0e4ee342fcec353b31434060feea0e01e89077 (diff) | |
download | pidgin-f543bef1f1b1cfd8bae65ebeb1bd63a4afc2a571.tar.gz |
Add search support to the contact list
This searches everything in `PurplePerson` and all of it's contacts, but does not yet cover tags. I am planning on covering that in another review request.
Right now the matching is just using `strstr`, but will will update this as part of [PIDGIN-17737](https://issues.imfreedom.org/issue/PIDGIN-17737/).
I also tried to figure out how to get focus back to the list view, but didn't come up with any viable solutions.
Testing Done:
Ran the unit tests and did a bunch of searches in the contact list with the demo protocol plugin.
Bugs closed: PIDGIN-17717
Reviewed at https://reviews.imfreedom.org/r/2211/
Diffstat (limited to 'libpurple')
-rw-r--r-- | libpurple/purplecontactinfo.c | 40 | ||||
-rw-r--r-- | libpurple/purplecontactinfo.h | 16 | ||||
-rw-r--r-- | libpurple/purpleperson.c | 34 | ||||
-rw-r--r-- | libpurple/purpleperson.h | 17 | ||||
-rw-r--r-- | libpurple/tests/test_contact_info.c | 91 | ||||
-rw-r--r-- | libpurple/tests/test_person.c | 58 |
6 files changed, 255 insertions, 1 deletions
diff --git a/libpurple/purplecontactinfo.c b/libpurple/purplecontactinfo.c index 9f29f8a509..4d73ee3fd2 100644 --- a/libpurple/purplecontactinfo.c +++ b/libpurple/purplecontactinfo.c @@ -797,3 +797,43 @@ purple_contact_info_compare(PurpleContactInfo *a, PurpleContactInfo *b) { return purple_utf8_strcasecmp(name_a, name_b); } + +gboolean +purple_contact_info_matches(PurpleContactInfo *info, const char *needle) { + PurpleContactInfoPrivate *priv = NULL; + + g_return_val_if_fail(PURPLE_IS_CONTACT_INFO(info), FALSE); + + if(purple_strempty(needle)) { + return TRUE; + } + + priv = purple_contact_info_get_instance_private(info); + + if(!purple_strempty(priv->id)) { + if(strstr(priv->id, needle) != NULL) { + return TRUE; + } + } + + if(!purple_strempty(priv->username)) { + if(strstr(priv->username, needle) != NULL) { + return TRUE; + } + } + + if(!purple_strempty(priv->alias)) { + if(strstr(priv->alias, needle) != NULL) { + return TRUE; + } + } + + if(!purple_strempty(priv->display_name)) { + if(strstr(priv->display_name, needle) != NULL) { + return TRUE; + } + } + + /* Nothing matched, so return FALSE. */ + return FALSE; +} diff --git a/libpurple/purplecontactinfo.h b/libpurple/purplecontactinfo.h index f0ef858521..e1bfc3ea7d 100644 --- a/libpurple/purplecontactinfo.h +++ b/libpurple/purplecontactinfo.h @@ -355,6 +355,22 @@ const char *purple_contact_info_get_name_for_display(PurpleContactInfo *info); */ int purple_contact_info_compare(PurpleContactInfo *a, PurpleContactInfo *b); +/** + * purple_contact_info_matches: + * @info: The instance. + * @needle: (nullable): The string to match. + * + * This will determine if the alias, display name, or username matches @needle. + * + * If @needle is %NULL or empty string, %TRUE will be returned. + * + * Returns: %TRUE if @needle matches any of the above properties, otherwise + * %FALSE. + * + * Since: 3.0.0 + */ +gboolean purple_contact_info_matches(PurpleContactInfo *info, const char *needle); + G_END_DECLS #endif /* PURPLE_CONTACT_INFO_H */ diff --git a/libpurple/purpleperson.c b/libpurple/purpleperson.c index 14d4cb1885..8545d653e0 100644 --- a/libpurple/purpleperson.c +++ b/libpurple/purpleperson.c @@ -20,6 +20,8 @@ #include "util.h" +#include "util.h" + struct _PurplePerson { GObject parent; @@ -122,6 +124,17 @@ purple_person_sort_contacts(PurplePerson *person) { } } +/* This function is used by purple_person_matches to determine if a contact info + * matches the needle. + */ +static gboolean +purple_person_matches_find_func(gconstpointer a, gconstpointer b) { + PurpleContactInfo *info = (gpointer)a; + const char *needle = b; + + return purple_contact_info_matches(info, needle); +} + /****************************************************************************** * Callbacks *****************************************************************************/ @@ -569,3 +582,24 @@ purple_person_has_contacts(PurplePerson *person) { return person->contacts->len > 0; } + +gboolean +purple_person_matches(PurplePerson *person, const char *needle) { + g_return_val_if_fail(PURPLE_IS_PERSON(person), FALSE); + + if(purple_strempty(needle)) { + return TRUE; + } + + /* Check if the person's alias matches. */ + if(!purple_strempty(person->alias)) { + if(strstr(person->alias, needle) != NULL) { + return TRUE; + } + } + + /* See if any of the contact infos match. */ + return g_ptr_array_find_with_equal_func(person->contacts, needle, + purple_person_matches_find_func, + NULL); +} diff --git a/libpurple/purpleperson.h b/libpurple/purpleperson.h index a7a64bed73..5d7111a5e6 100644 --- a/libpurple/purpleperson.h +++ b/libpurple/purpleperson.h @@ -220,6 +220,23 @@ PurpleContactInfo *purple_person_get_priority_contact_info(PurplePerson *person) */ gboolean purple_person_has_contacts(PurplePerson *person); +/** + * purple_person_matches: + * @person: The instance. + * @needle: (nullable): The string to match on. + * + * Checks if the alias matches @needle. This also checks @needle against + * [method@Purple.ContactInfo.matches] for each [class@Purple.ContactInfo] that + * @person is tracking. + * + * If @needle is %NULL or empty string, %TRUE will be returned. + * + * Returns: %TRUE if @person matches @needle in any way. + * + * Since: 3.0.0 + */ +gboolean purple_person_matches(PurplePerson *person, const char *needle); + G_END_DECLS #endif /* PURPLE_PERSON_H */ diff --git a/libpurple/tests/test_contact_info.c b/libpurple/tests/test_contact_info.c index cea1ed90e6..5584cf1e1f 100644 --- a/libpurple/tests/test_contact_info.c +++ b/libpurple/tests/test_contact_info.c @@ -315,6 +315,82 @@ test_purple_contact_info_compare_name__name(void) { } /****************************************************************************** + * Matches + *****************************************************************************/ +static void +test_purple_contact_info_matches_accepts_null(void) { + PurpleContactInfo *info = purple_contact_info_new(NULL); + + g_assert_true(purple_contact_info_matches(info, NULL)); + + g_clear_object(&info); +} + +static void +test_purple_contact_info_matches_empty_string(void) { + PurpleContactInfo *info = purple_contact_info_new(NULL); + + g_assert_true(purple_contact_info_matches(info, "")); + + g_clear_object(&info); +} + +static void +test_purple_contact_info_matches_id(void) { + PurpleContactInfo *info = purple_contact_info_new("this is an id"); + + g_assert_true(purple_contact_info_matches(info, "an")); + + g_clear_object(&info); +} + +static void +test_purple_contact_info_matches_username(void) { + PurpleContactInfo *info = purple_contact_info_new(NULL); + + purple_contact_info_set_username(info, "username"); + + g_assert_true(purple_contact_info_matches(info, "name")); + + g_clear_object(&info); +} + +static void +test_purple_contact_info_matches_alias(void) { + PurpleContactInfo *info = purple_contact_info_new(NULL); + + purple_contact_info_set_alias(info, "alias"); + + g_assert_true(purple_contact_info_matches(info, "lia")); + + g_clear_object(&info); +} + +static void +test_purple_contact_info_matches_display_name(void) { + PurpleContactInfo *info = purple_contact_info_new(NULL); + + purple_contact_info_set_display_name(info, "display name"); + + g_assert_true(purple_contact_info_matches(info, "play")); + + g_clear_object(&info); +} + +static void +test_purple_contact_info_matches_none(void) { + PurpleContactInfo *info = purple_contact_info_new("id"); + + purple_contact_info_set_username(info, "username"); + purple_contact_info_set_alias(info, "alias"); + purple_contact_info_set_display_name(info, "display name"); + + g_assert_false(purple_contact_info_matches(info, "nothing")); + + g_clear_object(&info); +} + +/****************************************************************************** * Main *****************************************************************************/ gint @@ -352,5 +428,20 @@ main(gint argc, gchar *argv[]) { g_test_add_func("/contact-info/compare/name__name", test_purple_contact_info_compare_name__name); + g_test_add_func("/contact-info/matches/accepts_null", + test_purple_contact_info_matches_accepts_null); + g_test_add_func("/contact-info/matches/emptry_string", + test_purple_contact_info_matches_empty_string); + g_test_add_func("/contact-info/matches/id", + test_purple_contact_info_matches_id); + g_test_add_func("/contact-info/matches/username", + test_purple_contact_info_matches_username); + g_test_add_func("/contact-info/matches/alias", + test_purple_contact_info_matches_alias); + g_test_add_func("/contact-info/matches/display_name", + test_purple_contact_info_matches_display_name); + g_test_add_func("/contact-info/matches/none", + test_purple_contact_info_matches_none); + return g_test_run(); } diff --git a/libpurple/tests/test_person.c b/libpurple/tests/test_person.c index f5e3cb3822..a47852b692 100644 --- a/libpurple/tests/test_person.c +++ b/libpurple/tests/test_person.c @@ -443,6 +443,53 @@ test_purple_person_priority_multiple_with_change(void) { } /****************************************************************************** + * Matches tests + *****************************************************************************/ +static void +test_purple_person_matches_accepts_null(void) { + PurplePerson *person = purple_person_new(); + + g_assert_true(purple_person_matches(person, NULL)); + + g_clear_object(&person); +} + +static void +test_purple_person_matches_empty_string(void) { + PurplePerson *person = purple_person_new(); + + g_assert_true(purple_person_matches(person, "")); + + g_clear_object(&person); +} + +static void +test_purple_person_matches_alias(void) { + PurplePerson *person = purple_person_new(); + + purple_person_set_alias(person, "this is the alias"); + + g_assert_true(purple_person_matches(person, "the")); + g_assert_false(purple_person_matches(person, "what")); + + g_clear_object(&person); +} + +static void +test_purple_person_matches_contact_info(void) { + PurplePerson *person = purple_person_new(); + PurpleContactInfo *info = purple_contact_info_new(NULL); + + purple_contact_info_set_username(info, "user1"); + purple_person_add_contact_info(person, info); + g_clear_object(&info); + + g_assert_true(purple_person_matches(person, "user1")); + + g_clear_object(&person); +} + +/****************************************************************************** * Main *****************************************************************************/ gint @@ -476,5 +523,14 @@ main(gint argc, gchar *argv[]) { g_test_add_func("/person/priority/multiple-with-change", test_purple_person_priority_multiple_with_change); + g_test_add_func("/person/matches/accepts_null", + test_purple_person_matches_accepts_null); + g_test_add_func("/person/matches/empty_string", + test_purple_person_matches_empty_string); + g_test_add_func("/person/matches/alias", + test_purple_person_matches_alias); + g_test_add_func("/person/matches/contact_info", + test_purple_person_matches_contact_info); + return g_test_run(); -}
\ No newline at end of file +} |